SSMS 2005 - 返回不同结果的非别名列

时间:2016-12-08 22:28:13

标签: sql-server sql-server-2005

我甚至无法想到如何说出这个标题。这是SQL Server 2005

如果我使用列上的别名执行相同的查询,而不使用,则会得到完全不同的结果。这不是模棱两可的。

示例查询:

    UPDATE  MyTable
SET     Col1 = Col1 - 1
FROM    DB.dbo.MyTable M
WHERE   EXISTS ( SELECT *
                 FROM   DB.dbo.SecondTable B WITH ( NOLOCK )
                 WHERE  B.Col2 = 12345678
                        AND B.Col3 = 1
                        AND B.M-FK = M.M-PK )
        AND M.Col1 > 0
        AND M.Col4 = 87654321;

这个查询我直接把所有东西都假装到了表中,并得到了相当大的回报。

非常相似的查询,但我没有指定表

UPDATE  MyTable
SET     Col1 = Col1 - 1
FROM    DB.dbo.MyTable M
WHERE   EXISTS ( SELECT *
                 FROM   DB.dbo.SecondTable B WITH ( NOLOCK )
                 WHERE  Col2 = 12345678
                        AND Col3 = 1
                        AND B.M-FK = M.M-PK )
        AND Col1 > 0
        AND Col4 = 87654321;

第二个查询返回1.

此之间的相互列是B-ForeignKey => M.PrimaryKey

根据我的经验,我总是将列分配给别名,但是当有人早些时候问我上述问题时,我发现自己很困惑。如果它们含糊不清,SSMS会拒绝它。但是,它实际上已经运行了。

所以我想也许'它忽略了那些列 - 这很奇怪。 但是第二次返回-1-行,这增加了更多的混乱。

有人能解释为什么别名与非别名查询会发生变化吗?如果它出现错误,它为什么会完成?

2 个答案:

答案 0 :(得分:1)

根据我的经验,我从不直接通过数据库名称来引用表。我总是 Alias ,因为它更易于阅读,并且在相同的精确列名和数据类型跨越两个或更多的情况下,我也明确指出了哪些列表。

尝试这一点并坚持使用相同的设计,你将始终得到你期望的结果:

UPDATE  m
SET     m.Col1 = m.Col1 - 1
FROM    dbo.MyTable AS m
WHERE   EXISTS ( SELECT *
                 FROM   dbo.SecondTable AS b WITH ( NOLOCK )
                 WHERE  b.Col2 = 12345678
                        AND b.Col3 = 1
                        AND b.M-FK = m.M-PK )
        AND m.Col1 > 0
        AND m.Col4 = 87654321;

AS反对......

UPDATE  dbo.MyTable
SET     Col1 = Col1 - 1
WHERE   EXISTS ( SELECT *
                 FROM   dbo.SecondTable AS b WITH ( NOLOCK )
                 WHERE  b.Col2 = 12345678
                        AND b.Col3 = 1
                        AND b.M-FK = M-PK )
        AND Col1 > 0
        AND Col4 = 87654321;

第二个版本的问题是SQL可能会在两个表之间混淆,如果两个表有一个或多个相同的列定义。实际上它可能甚至不会运行错误!因此,为什么使用别名,我知道我指的是什么表,它只更新我想要的列和表。

这是一个提示:

将UPDATE视为"壶壶盖",其中锅的优点"" (SELECT语句)在锅内!

即:

UPDATE a
SET a.col1 = @value1, a.col2 = @value2, etc
FROM dbo.myTable1 AS a
  INNER JOIN dbo.myTable2 as b ON b.col3 = a.col3
  INNER JOIN ...etc..
WHERE ..etc..

请注意,从FROM子句中,它就像SELECT一样。而且您不必更新查询中的第一个表。您可以更新b或UPDATE c等,而不会影响查询的FROM子句中的逻辑。

所以我的建议是编写一个SELECT查询来获取您想要的数据,使其工作,然后将SELECT替换为UPDATE & SET,具体取决于您要更改的列。这样我就不会对我正在改变的数据感到困惑。

我设法以这种方式创建大量的UPDATE SQL语句,并使它们几乎第一次工作。

干杯

答案 1 :(得分:0)

如果任何列引用含糊不清,则会出现错误。这些查询对我来说看起来是一样的,但谓词Col1 > 0可能会在每次执行后过滤掉不同的行,因为你要减少它们。另外,我假设B.M-FK是你混淆的工件,因为它被解释为B.M - B.FK。我假设您的意思是B.[M-FK]B.M_FK

我也看到(NOLOCK)。如果数据在B中变化,可能会有所贡献。