SQL 使用 SELECT 执行 INSERT 以插入多条记录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/601906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 01:19:33  来源:igfitidea点击:

Perform INSERT with SELECT to insert multiple records

sqlsql-serversql-server-2005

提问by Matthew Dresser

In the diagram below there is a 1:1 relationship between 'DodgyOldTable' and 'MainTable'. Table 'Option' contains records with 'OptionVal1', 'OptionVal2' and 'OptionVal3' in the 'OptionDesc' field. I need to do an insert into MainTable_Option with a select from DodgyOldTable. Something like this:

在下图中,“DodgyOldTable”和“MainTable”之间存在 1:1 的关系。表“Option”在“OptionDesc”字段中包含带有“OptionVal1”、“OptionVal2”和“OptionVal3”的记录。我需要使用 DodgyOldTable 中的选择插入 MainTable_Option。像这样的东西:

INSERT MainTable_Option ([MainTableID],[OptionID])
SELECT ID, (CASE WHEN OptionVal1 = 'y' THEN 
    (SELECT OptionID 
     FROM Option 
     WHERE OptionDesc = 'OptionVal1') END
FROM DodgyOldTable

If possible I want to avoid using several different select statements to perform the insert operation.

如果可能,我想避免使用几个不同的 select 语句来执行插入操作。

alt text http://www.freeimagehosting.net/uploads/863f10bf5f.jpg

替代文字 http://www.freeimagehosting.net/uploads/863f10bf5f.jpg

回答by Tomalak

INSERT 
  MainTable_Option 
  (
  MainTableID, 
  OptionID
  )
SELECT
  d.ID, 
  o.OptionId
FROM
  DodgyOldTable d
  INNER JOIN Option o ON
    (d.OptionVal1 = 'Y' AND o.OptionDesc = 'OptionVal1') OR
    (d.OptionVal2 = 'Y' AND o.OptionDesc = 'OptionVal2') OR
    (d.OptionVal3 = 'Y' AND o.OptionDesc = 'OptionVal3')

回答by Lieven Keersmaekers

perhaps not the most efficient solution but by using a union, this should work.

也许不是最有效的解决方案,但通过使用联合,这应该有效。

INSERT MainTable_Option ([MainTableID],[OptionID])
SELECT ID, (SELECT OptionID FROM Option WHERE OptionDesc = 'OptionVal1')
FROM DodgyOldTable dot
WHERE OptionVal1 = 'y'
UNION SELECT ID, (SELECT OptionID FROM Option WHERE OptionDesc = 'OptionVal2')
FROM DodgyOldTable dot
WHERE OptionVal2 = 'y'
UNION SELECT ID, (SELECT OptionID FROM Option WHERE OptionDesc = 'OptionVal3')
FROM DodgyOldTable dot
WHERE OptionVal3 = 'y'

回答by Roel Snetselaar

My experience is it is often more easy and more readable to divide it up into smaller bits. So don't try to do everything in one single query. Especially when you are making migration scripts this should not be an issue.

我的经验是将它分成更小的部分通常更容易和更易读。所以不要试图在一个查询中完成所有事情。特别是当您制作迁移脚本时,这应该不是问题。

Write down the steps, maybe introduce a temporary table, write the scripts to migrate your data and you are good to go!

写下步骤,也许引入一个临时表,编写迁移数据的脚本,你就可以开始了!

回答by Maksym Gontar

What about CROSS JOIN solution?

CROSS JOIN 解决方案怎么样?

DECLARE @DodgyOldTable TABLE (ID INT, OptionVal1 CHAR, OptionVal2 CHAR, 
  OptionVal3 CHAR)
INSERT INTO @DodgyOldTable
SELECT 1, 'y', 'n', 'y' UNION
SELECT 2, 'y', 'n', 'n' UNION
SELECT 3, 'n', 'n', 'y' UNION
SELECT 4, 'y', 'y', 'y' UNION
SELECT 5, 'n', 'n', 'n'

DECLARE @Option TABLE (OptionID INT, OptionDesc VARCHAR(100))
INSERT INTO @Option
SELECT 1, 'OptionVal1' UNION
SELECT 2, 'OptionVal2' UNION
SELECT 3, 'OptionVal3'

SELECT ID, OptionID FROM
(
    SELECT 
        ID, 
        CASE    
          WHEN (OptionVal1 = 'y' AND OptionDesc = 'OptionVal1') 
            OR (OptionVal2 = 'y' AND OptionDesc = 'OptionVal2') 
            OR (OptionVal3 = 'y' AND OptionDesc = 'OptionVal3')
          THEN OptionID 
          ELSE NULL 
        END AS OptionID 
    FROM @DodgyOldTable DOT CROSS JOIN @Option O 
)CRS
WHERE OptionID IS NOT NULL

回答by Juan Kev

11 Yrs later but might help someone:

11 年后,但可能会帮助某人:

INSERT INTO schema.tableName (col1, col2,col3, col4, col5, col6, col7)
      SELECT col1, 
             col2,
             'Static value',
             CURRENT_TIMESTAMP,
             'Anothe static value', 
             1, 
             (SELECT col7 FROM schema2.anotherTableName)
       FROM schema.tableX;

col1 & col2 come from the same select

col3, col5 are static strings

col4 is the current system time

col6 a Num value,

col7 from a select that returns one value.

col1 & col2 来自同一个选择

col3, col5 是静态字符串

col4 是当前系统时间

col6 Num 值,

col7 来自返回一个值的选择。

NB: Ensure the select with multiple values comes at the beginning. This is MySQL

注意:确保具有多个值的选择位于开头。这是 MySQL

回答by Rich Andrews

You could UNION all of selects together to give one result set but it depends on your reasons for not wanting the multiple selects - if there are too many or the number of selects may change frequently it'll still be a pain to amend the query with the additional selects. Unfortunatly I think you will have to put the logic somewhere that determines which bit(s) of DodgyOldTable map to the new structure and either write a migration script (or SSIS package) to bulk migrate (if this is a one off job) or UNION your results together...

您可以将所有选择联合在一起以提供一个结果集,但这取决于您不想要多个选择的原因 - 如果选择过多或选择数量可能经常变化,那么修改查询仍然很痛苦额外的选择。不幸的是,我认为您必须将逻辑放在某处,以确定 DodgyOldTable 的哪些位映射到新结构,并编写迁移脚本(或 SSIS 包)以进行批量迁移(如果这是一次性工作)或 UNION你们在一起的结果...

INSERT MainTable_Option ([MainTableID],[OptionID])
SELECT ID, (CASE WHEN OptionVal1 = 'y' THEN (SELECT OptionID FROM Option WHERE OptionDesc = 'OptionVal1') END
FROM DodgyOldTable
WHERE OptionVal1 = 'y
UNION
SELECT ID, (CASE WHEN OptionVal2 = 'y' THEN (SELECT OptionID FROM Option WHERE OptionDesc = 'OptionVal2') END
FROM DodgyOldTable
WHERE OptionVal2 = 'y
...

回答by thr

I'd say that a manual migration script would be easier to use then trying to do it in a single sql query, if that is an option.

我会说手动迁移脚本会更容易使用,然后尝试在单个 sql 查询中执行它,如果这是一个选项。