【问题标题】:How to conditional INSERT INTO from different tables?如何有条件地从不同的表中插入 INSERT INTO?
【发布时间】:2019-01-20 13:20:21
【问题描述】:

我正在编写一个存储过程来做一些常见的检查,在存储过程中我有如下代码以避免创建太多@variables

IF type = 'spl' 
THEN BEGIN
    SELECT col1, col4, col5, col9, col20, ... INTO #tmp
    FROM tbl1 
    WHERE primary_key = unique_id
END
ELSE BEGIN
    SELECT col1, col5, col7, col8, col19, ... INTO #tmp
    FROM tbl2
    WHERE primary_key = unique_id
END

虽然这两个INSERT 永远不能同时运行,但仍然会导致#tmp table already exist 错误,并且无法创建存储过程。

有什么常见的解决方法吗?

以下当然是可能的,但它看起来比声明几十个@variables 更糟糕。但这是我唯一能想到的atm。

SELECT * 
INTO #TEMP 
FROM 
     (SELECT 
          CASE WHEN type = 'spl' 
                  THEN a.col1 
                  ELSE b.col1 
               END, 
   ...
   FROM ... CROSS JOIN ... 
)

【问题讨论】:

  • 如果两个select语句以相同的顺序返回相同数量的相同数据类型的列,您可以先创建临时表(使用create table #temp) and then insert...select`而不是@987654329 @。如果没有,您可以使用两个不同的表。如果没有更多上下文,很难给出一个好的答案。
  • 这很可能是XY problem。所以在选择路径时要小心。为什么?在您的临时表中创建了哪些列?如果您不小心,您将获得一个包含名称因您的逻辑而异的列的表。然后你会发现很难使用这个表。佐哈尔间接谈到了这一点。当然,我们希望您的“col1”、“col4”等是经过混淆的列名。但我在现实生活中看到过,这不是一个好兆头。
  • 您可以使用insert into ... select ... from tbl1 where @type = 'spl' and primary_key = unique_id union all select ... from tbl2 where @type <> 'spl' and primary_key = unique_id,但执行单独的查询应该更清晰、更高效。提示:您可以使用select .. into #tmp where 42 = 6 * 9; 创建一个空的临时表。不可能的条件将阻止添加行。
  • 谢谢,伙计们。这么多好点。我得到了你的答案。避免繁琐的列类型声明;我应该SELECT col1 alias1, col3 alias1, colM aliasN into #temp from table1 where 1=2 为我创建空表,然后有条件地创建INSERT INTO。如果有人可以写答案,我会投票给他们。
  • 我认为@HABO 提出了 cmets 中的最佳解决方案,所以...

标签: sql-server tsql sql-server-2012 insert-into


【解决方案1】:

您可以通过将多个数据源与union all 组合并使用单独的where 子句从多个数据源执行“条件”插入,这将导致仅一个数据源生成行:

insert into #tmp
  select col1, col2, ...
    from tbl1
    where @type = 'spl' and primary_key = unique_id
  union all
  select col1, col2, ...
    from tbl2
    where @type <> 'spl' and primary_key = unique_id;

如果您想为您创建输出表,您可以使用select ... into ...where 子句来防止插入任何行。结果将是一个具有正确架构的空表:

-- Create empty   #tmp   table.
select col1, col2, ...
  from tbl1
  into #tmp
  where 42 = 6 * 9; -- Answer to the Ultimate Question of Life, the Universe, and Everything.

请注意,使用 if/then 执行单独的查询允许查询优化器为每个查询生成最佳计划,而不是整个 union all 混搭,它使意图更清晰长期维护。

这也是阅读parameter sniffing 的好时机。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 2018-11-13
    相关资源
    最近更新 更多