1

不同模式的相同查询?

你好,

我有一个查询。它在表中查询一些数据。但是,因为有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 会先编译整个查询吗?要不然?

有人知道解决方案吗?

谢谢

4

3 回答 3

5

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

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

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

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

于 2013-03-25T18:33:27.870 回答
2

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

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

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

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

于 2013-03-25T18:33:37.240 回答
0

另一种解决方案可能是在 table1 上创建一个数据库视图,其字段名为title_Name(定义为版本 #1 的 table1.Name 和版本 #2 的 table1.title),并使用数据库视图而不是 table1您的查询,像这样加入:

INNER JOIN table3 t3 on t1.title_Name = t3.Name 
于 2013-03-25T18:44:58.937 回答