针对不同架构的相同查询?
您好,
我有一个查询。它在表中查询某些数据。但是,由于数据库有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是否首先编译整个查询?或者,否则?
任何人都知道解决方案吗?
感谢
答案 0 :(得分:5)
SQL将尝试解析和评估所有列引用。您可以通过引用不存在的表(延迟名称解析)来逃避,但是您无法使用表中不存在的列。解析器不关心您的IF
和其他条件逻辑在运行时可能会产生什么。这就是为什么你不能这样做的原因:
IF (1=1)
CREATE TABLE #foo...
ELSE
CREATE TABLE #foo...
即使ELSE
永远不可能运行,解析器也会阻止这么简单的事情。
是的,解决这个问题的方法是动态SQL(或者首先是更稳定的设计)。
答案 1 :(得分:2)
您需要使用exec
来解决这个问题。问题出现在处理的编译阶段。它没有找到表中的列(谢谢Aaron),所以它失败了。
不幸的是,您无法使用if
或try 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