Faj*_*iya 7 sql-server t-sql errors
为什么下面的批次不能按预期工作?
DROP TABLE IF EXISTS #test1;
IF 1 = 1
SELECT *
INTO #test1
FROM sys.databases
WHERE database_id <= 5;
ELSE
SELECT *
INTO #test1
FROM sys.databases;
SELECT *
FROM #test1;
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到:
消息 2714,级别 16,状态 1,第 12 行 数据库中已有一个名为“#test1”的对象。
我必须像这样更改代码:
DROP TABLE IF EXISTS ##test1;
IF 1 = 1
EXEC ('
SELECT *
INTO ##test1
FROM sys.databases
WHERE database_id <= 5;
' );
ELSE
EXEC ('
SELECT *
INTO ##test1
FROM sys.databases;');
SELECT *
FROM ##test1;
Run Code Online (Sandbox Code Playgroud)
这按预期工作。上述错误似乎是一个解析错误,我不确定。谁能帮忙解释一下这里发生了什么?
该错误是在解析时生成的,因此在批处理执行之前。仅当INTO目标是临时表(本地或全局)时才会发生这种情况。当目标是常规表时,不会发生这种情况。
解决此问题的一种方法是使用动态 SQL,如您所示。正如您还发现的那样,该方法不适用于本地临时表,这可能并不总是很好。
您还可以按照 Aleksey Vitsko 的建议,预先创建目标表并改为使用INSERT...SELECT来填充它。我认为这可能不方便的一种情况是,当查询返回多个计算列时,因为您首先必须正确确定数据类型,以便适应输出数据,而不会导致溢出、精度损失、转换错误或其他此类情况。SELECT...INTO
要解决这两个问题(继续使用本地临时表,避免显式定义目标列),您可以尝试像这样重写脚本:
DROP TABLE IF EXISTS #test1;
/* the query from the "if true" branch */
SELECT
*
INTO
#test1
FROM
sys.databases
WHERE
database_id <= 5
AND ... /* your IF condition should go here */
;
IF NOT (...) /* the negated version of your IF condition goes here;
make sure to account for possible "unknowns" */
/* the "else" branch query */
INSERT INTO
#test1
SELECT
*
FROM
sys.databases
;
SELECT * FROM #test1;
Run Code Online (Sandbox Code Playgroud)
第一个查询将运行并创建目标表。如果IF条件为真,表也将被填充,否则表将为空。如果条件不成立,下一条语句将填充创建的表。