【发布时间】:2011-03-02 05:58:03
【问题描述】:
我有一个包含 VARCHAR 类型的邮政编码字段的地址表。 我需要使用邮政编码范围从该表中选择所有地址。 如果我使用下一个代码:
select * from address where cast(zip as bigint) between 90210 and 90220
在无法将邮政编码转换为 bigint 的字段中出现错误。
我该如何解决这个问题?
【问题讨论】:
我有一个包含 VARCHAR 类型的邮政编码字段的地址表。 我需要使用邮政编码范围从该表中选择所有地址。 如果我使用下一个代码:
select * from address where cast(zip as bigint) between 90210 and 90220
在无法将邮政编码转换为 bigint 的字段中出现错误。
我该如何解决这个问题?
【问题讨论】:
如果 zip 值是数字,则派生一个版本的 zip 列,它是一个 bigint,否则为 null,然后对其进行测试。
有点像
select * from address
where case when zip ~ '^[0-9]+$' then cast(zip as bigint) end between 90210 and 90220
为了让这个查询更高效,你可以在这个表达式上创建一个索引:
create index address_zip_idx on address(cast(zip as bigint)) where zip ~ '^[0-9]+$';
-- this query can now use that index
select * from address
where zip ~ '^[0-9]+$' and cast(zip as bigint) between 90210 and 90220;
【讨论】:
错误很明显:您有一些 zip 地址不代表数字。例如,字母或破折号。如果你想将它们解释为数字,那么你必须摆脱那些不是由数字组成的......如果这真的适合你。有关一些食谱,请参阅 araqnid 的答案。 但首先问问自己,如果您有一些 ZIP 编号存储为“123-34”,您想如何解释它们,也许您需要重新考虑格式和数据类型。
【讨论】:
如果您只有美国邮政编码,那么您可能应该有两个 int 列,例如 zip 和 plus_4。但是对您的问题的简单回答是只进行 varchar 比较。您可能已经为 zip 列建立了索引,所以这仍然可以很好地工作。
SELECT * FROM address WHERE zip BETWEEN '90210' AND '90220'
【讨论】: