利用BETWEEN AND比较字符串获得一个首字母为 B 和 N 之间的数据问题

本文探讨了在使用BETWEEN AND操作符进行字符串比较时遇到的问题,例如在SQL查询中未正确筛选出首字母位于B和N之间的数据。以Newtown为例,尽管它以N开头,但并未出现在预期的结果中。文章将揭示这个问题的原因并提出解决方案。
创建表和准备数据
CREATE TABLE customer
(
 customer_id serial ,
 title char(4) ,
 fname varchar(32) ,
 lname varchar(32) NOT NULL,
 addressline varchar(64) ,
 town varchar(32) ,
 zipcode char(10) NOT NULL,
 phone varchar(16) ,
 CONSTRAINT customer_pk PRIMARY KEY(customer_id)
);

INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone)
VALUES('Miss','Jenny','Stones','27 Rowan Avenue','Hightown','NT2 1AQ','023 9876');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone)
VALUES('Mr','Andrew','Stones','52 The Willows','Lowtown','LT5 7RA','876 3527');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Miss','Alex','Matthew','4 The Street','Nicetown','NT2 2TX','010 4567');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Adrian','Matthew','The Barn','Yuleville','YV67 2WR','487 3871');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Simon','Cozens','7 Shady Lane','Oakenham','OA3 6QW','514 5926');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Neil','Matthew','5 Pasture Lane','Nicetown','NT3 7RT','267 1232');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Richard','Stones','34 Holly Way','Bingham','BG4 2WE','342 5982');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mrs','Ann','Stones','34 Holly Way','Bingham','BG4 2WE','342 5982');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mrs','Christine','Hickman','36 Queen Street','Histon','HT3 5EM','342 5432');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Mike','Howard','86 Dysart Street','Tibsville','TB3 7FG','505 5482');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Dave','Jones','54 Vale Rise','Bingham','BG3 8GD','342 8264');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Richard','Neill','42 Thatched Way','Winersby','WB3 6GQ','505 6482');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mrs','Laura','Hardy','73 Margarita Way','Oxbridge','OX2 3HX','821 2335');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','Bill','O\'Neill','2 Beamer Street','Welltown','WT3 8GM','435 1234');
INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) 
VALUES('Mr','David','Hudson','4 The Square','Milltown','MT2 6RT','961 4526');

 
使用 BETWEEN 比较字符串。假设我们想获得一个首字母为 B N 之间的所有不同城镇的列表。我们可以依照以下的写法:
SELECT DISTINCT town FROM customer WHERE town BETWEEN 'B' AND 'N';

从上图结果,我们发现现这个 SQL 没有达到如期的效果。Newtown 没有被列出来,而它是以字母 N 开始的。

这条语句没有达到我们效果的原因是依照 SQL 标准,用填充你给的字符串到需要比较的字符串的长度然后再比较。所以当我们比较 Newtown 的时候,用“N ”(N 后面填充了六个空白)和 Newtown,而空 白在 ASCII 表中的位置再其他所有字符之前,所以判断的结果是 Newtown 比“N ”大,所以它不应该在结果列表中.

解决方法

SELECT DISTINCT town FROM customer WHERE town BETWEEN 'B' AND 'Nz';

注意我们没有在 B 之后加上 z,因为 B 后添加空格确实能匹配到 B 开头的所有城镇,因为它是一个开始点而不是结束点。还要注意如果一个城镇开始于字符 Nzz,我们仍将无法找到它,因为我们将用“Nz ”与 Nzz 比较,然后确定 Nzz 在 Nz 之后,因为字符串 Nz 字符串依旧被填充了一个空白,而空白的位置比我们比较的字符串相对位置的字符 z 的位置靠前。
这种比较确实有一些很微妙的行为,所以如果你确实要使用 BETWEEN 比较字符串,需要仔细考虑关于需要匹配的 内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值