0

我需要在我的数据库中找到丢失的数字。我正在比较两个数据库,即在查询中创建的带有数字 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]%'

我收到一个错误“将 varchar 转换为 int”,但我不知道为什么。当我将左连接更改为右连接时,我没有收到任何错误。

我还手动检查了两个数据库,没有字符串或字符,只有整数。

我也尝试了 CONVERT() 但结果相同。

有什么建议或想法有什么问题吗?

编辑:

1 - 我在 rextester 上尝试时发现一个错误。I added MYDAT.ID IS NULL到查询,所以我得到正确的结果。

2 - 我需要这个的例子:http ://rextester.com/KFG73206

但 CAST 或 CONVERT 似乎不起作用http://rextester.com/WJIAH52304

4

3 回答 3

1

您确实说过“缺少数字”,所以 tempdb 中不在 MYDAT 中的东西就是您所追求的吗?如果是这样,请参阅:http ://rextester.com/HCB88714

于 2017-07-06T10:54:22.320 回答
0

无法明确说明原因,可能是数据问题。您可以尝试一些解决方法来避免投射,

 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]%'
于 2017-07-06T10:17:30.363 回答
0

问题是where子句不一定在子句之前执行on。SQL Server 可以重新排列操作。

我猜你真的想与 . 的前三个字符进行比较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 之前的版本中,您可以使用 acase代替:

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确实保证了评估的顺序。

于 2017-07-06T10:47:38.343 回答