对于具有不同列(针对不同版本)的相同表的相同查询?

时间:2013-03-25 18:30:44

标签: sql sql-server sql-server-2008

针对不同架构的相同查询?

您好,

我有一个查询。它在表中查询某些数据。但是,由于数据库有2个不同版本,因此表列已更改。例如:

对于版本#1,table1具有列:id,value,name 对于版本#2,table1具有列:id,value,title

(当它是#2时,数据库中有一个新的table2。我用来决定它是#1还是#2。)

现在,我需要编写一个查询以在一个查询中适应这两个版本。

            IF OBJECT_ID('dbo.table2', 'U') IS NULL
            BEGIN
                -- version #1
                SELECT *
                FROM table1 t1 INNER JOIN table3 t3 on t1.Name = t3.Name ......
                ...

            END
            ELSE
            BEGIN
                -- version #2
                SELECT *
                FROM table1 t1 INNER JOIN table3 t3 on t1.title = t3.Name ......
                ...
            END

当我为版本#2运行它时,它会报告错误:t1.Name无效的列名。

我想可能,我可以使用EXEC来解决这个问题。有更优雅的方式吗?

我尝试过TRY CATCH,它仍然报告同样的错误。

我发现的奇怪之处是:我有另一个查询,它确实:

1)创建一个临时表#Ldap 2)使用openquery(对于活动目录)将一些数据插入临时表#Ldap。 3)然后使用上述逻辑来确定它是版本#1还是#2。

虽然它在管理工作室的编辑器中突出显示t1.Name为错误,但它工作正常。它没有报告错误。

这让我想知道:SQL是否首先编译整个查询?或者,否则?

任何人都知道解决方案吗?

感谢

3 个答案:

答案 0 :(得分:5)

SQL将尝试解析和评估所有列引用。您可以通过引用不存在的表(延迟名称解析)来逃避,但是您无法使用表中不存在的列。解析器不关心您的IF和其他条件逻辑在运行时可能会产生什么。这就是为什么你不能这样做的原因:

IF (1=1)
  CREATE TABLE #foo...
ELSE
  CREATE TABLE #foo...

即使ELSE永远不可能运行,解析器也会阻止这么简单的事情。

是的,解决这个问题的方法是动态SQL(或者首先是更稳定的设计)。

答案 1 :(得分:2)

您需要使用exec来解决这个问题。问题出现在处理的编译阶段。它没有找到表中的列(谢谢Aaron),所以它失败了。

不幸的是,您无法使用iftry catch块来捕获编译时错误。

但是,您似乎理解正确的解决方案,即使用动态SQL。

您也可以通过在t1上创建两个版本中具有相同列名的视图,然后使用该视图来解决此问题。

答案 2 :(得分:0)

另一种解决方案可能是在table1上创建一个数据库视图,其中的字段名为title_Name(对于版本#1定义为table1.Name,对于版本#2定义为table1.title),以及在查询中使用数据库视图而不是table1,如下所示加入:

INNER JOIN table3 t3 on t1.title_Name = t3.Name