SQL 通过连接两个表将 varchar 转换为 int 时出错
SQL error while converting varchar to int by joining two tables
我需要在我的数据库中查找丢失的号码。我正在比较两个数据库,在查询中使用数字 1 - 999 创建的 tempdb 和 MYDAT。
MYDAT 看起来像:
+-------+
| id |
+-------+
| A-001 |
| A-002 |
| A-004 |
| A-... |
| A-952 |
| A-... |
+-------+
我是运行这个查询:
declare @tempid int
set @tempid = 1
create table tempdb (tempid int)
while @tempid < 1000
begin
insert into tempdb values(@tempid)
set @tempid = @tempid + 1
end
select tempdb.tempid from tempdb
left join MYDAT on tempdb.tempid = CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT)
where
MYDAT.ID IS NULL and
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
drop table tempdb
在不删除 temdb 的情况下,select * from tempdb
看起来不错,我得到了我想要的。
从 MYDAT 中选择和转换数据的部分效果很好,我只得到整数
select CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT) fom MYDAT
where
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
我遇到错误 "converting varchar to int" 但我不知道为什么。当我将左连接更改为右连接时,我没有收到任何错误。
我也手动检查了两个数据库,没有字符串或字符,只有整数。
我也尝试了 CONVERT() 但结果相同。
任何建议或想法是什么问题?
编辑:
1 - 我在 rextester 上尝试时看到一个错误。 I added MYDAT.ID IS NULL
到查询,以便我得到正确的结果。
2 - 示例
我需要这个:http://rextester.com/KFG73206
但是 CAST 或 CONVERT 似乎不起作用 http://rextester.com/WJIAH52304
无法明确说明原因,可能是数据的问题。您可以尝试一些解决方法来避免投射,
create table tempdb (tempid varchar(3))
while @tempid < 1000
begin
insert into tempdb values(@tempid)
set @tempid = @tempid + 1
end
select tempdb.tempid from tempdb
left join MYDAT on tempdb.tempid = SUBSTRING(MYDAT.ID, 3, 3)
where
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
问题在于 where
子句不一定在 on
子句之前 执行 。 SQL 服务器可以重新安排操作。
我猜你真的想比较MYDAT.ID
的前三个字符。这稍微简化了事情,因为您可以在下面的代码中使用 LEFT()
。事实上,你的 where
条件看起来不对,所以我修正了它们。
最好的解决方案是try_convert()
:
select tempdb.tempid
from tempdb left join
MYDAT
on tempdb.tempid = try_convert(int, left(MYDAT.ID, 3) )
where MYDAT.ID <> '' and
left(MYDAT.ID, 3) <> '000' and
left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%';
在 SQL Server 2012 之前的版本中,您可以使用 case
代替:
select tempdb.tempid
from tempdb left join
MYDAT
on tempdb.tempid = (case when left(MYDAT.ID, 1, 3) not like '%[^0-9]%')
then convert(int, left(MYDAT.ID, 3)
end)
where MYDAT.ID <> '' and
left(MYDAT.ID, 3) <> '000' and
left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%';
case
确实保证了求值顺序。
您确实说过 'missing numbers' 所以 tempdb 中不在 MYDAT 中的东西就是您所追求的?如果是,请参阅:http://rextester.com/HCB88714
我需要在我的数据库中查找丢失的号码。我正在比较两个数据库,在查询中使用数字 1 - 999 创建的 tempdb 和 MYDAT。
MYDAT 看起来像:
+-------+
| id |
+-------+
| A-001 |
| A-002 |
| A-004 |
| A-... |
| A-952 |
| A-... |
+-------+
我是运行这个查询:
declare @tempid int
set @tempid = 1
create table tempdb (tempid int)
while @tempid < 1000
begin
insert into tempdb values(@tempid)
set @tempid = @tempid + 1
end
select tempdb.tempid from tempdb
left join MYDAT on tempdb.tempid = CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT)
where
MYDAT.ID IS NULL and
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
drop table tempdb
在不删除 temdb 的情况下,select * from tempdb
看起来不错,我得到了我想要的。
从 MYDAT 中选择和转换数据的部分效果很好,我只得到整数
select CAST(SUBSTRING(MYDAT.ID, 3, 3) as INT) fom MYDAT
where
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
我遇到错误 "converting varchar to int" 但我不知道为什么。当我将左连接更改为右连接时,我没有收到任何错误。
我也手动检查了两个数据库,没有字符串或字符,只有整数。
我也尝试了 CONVERT() 但结果相同。
任何建议或想法是什么问题?
编辑:
1 - 我在 rextester 上尝试时看到一个错误。 I added MYDAT.ID IS NULL
到查询,以便我得到正确的结果。
2 - 示例 我需要这个:http://rextester.com/KFG73206
但是 CAST 或 CONVERT 似乎不起作用 http://rextester.com/WJIAH52304
无法明确说明原因,可能是数据的问题。您可以尝试一些解决方法来避免投射,
create table tempdb (tempid varchar(3))
while @tempid < 1000
begin
insert into tempdb values(@tempid)
set @tempid = @tempid + 1
end
select tempdb.tempid from tempdb
left join MYDAT on tempdb.tempid = SUBSTRING(MYDAT.ID, 3, 3)
where
SUBSTRING(MYDAT.ID, 3, 3) <> '' and
SUBSTRING(MYDAT.ID, 3, 3) <> '000'and
SUBSTRING(MYDAT.ID, 3, 3) NOT LIKE '%[^0-9]%'
问题在于 where
子句不一定在 on
子句之前 执行 。 SQL 服务器可以重新安排操作。
我猜你真的想比较MYDAT.ID
的前三个字符。这稍微简化了事情,因为您可以在下面的代码中使用 LEFT()
。事实上,你的 where
条件看起来不对,所以我修正了它们。
最好的解决方案是try_convert()
:
select tempdb.tempid
from tempdb left join
MYDAT
on tempdb.tempid = try_convert(int, left(MYDAT.ID, 3) )
where MYDAT.ID <> '' and
left(MYDAT.ID, 3) <> '000' and
left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%';
在 SQL Server 2012 之前的版本中,您可以使用 case
代替:
select tempdb.tempid
from tempdb left join
MYDAT
on tempdb.tempid = (case when left(MYDAT.ID, 1, 3) not like '%[^0-9]%')
then convert(int, left(MYDAT.ID, 3)
end)
where MYDAT.ID <> '' and
left(MYDAT.ID, 3) <> '000' and
left(MYDAT.ID, 3) NOT LIKE '%[^0-9]%';
case
确实保证了求值顺序。
您确实说过 'missing numbers' 所以 tempdb 中不在 MYDAT 中的东西就是您所追求的?如果是,请参阅:http://rextester.com/HCB88714