SQL 插入到存在列的位置

Posted

技术标签:

【中文标题】SQL 插入到存在列的位置【英文标题】:SQL insert into where columns exist 【发布时间】:2012-08-14 09:49:56 【问题描述】:

我在使用 SQL 插入语句时遇到问题。

目前,Insert 语句用于将数据从 .CSV 文件传输到 SQL 表中,但 .CSV 文件的内容可能会有所不同,即它可能包含与之前不同的列。

我用来从 .CSV 文件中获取数据的语句支持不同的列,因为它创建了一个与 .CSV 完全相同的临时表。

我目前使用的插入语句是:

INSERT INTO RTCU(ItemDATE, ItemTIME, SITENAME, GENSETNAME, GENSET_SN, REASON, EVENT, RPM, Pwr
                 ,Gfrq ,Vg1 ,Vg2 ,Vg3 ,Vg12 ,Vg23 ,Vg31, Ig1, Ig2, Ig3, Mfrq, Vm1, Vm2, Vm3
                 ,Vm12 ,Vm23 ,Vm31 ,BIN ,BOUT ,Mode ,CCpres ,OilLev
                 ,ActDem ,OilT ,AirInT ,RecAT ,JWTout ,JWTin ,JWGKin ,CylA1 ,CylA2 ,CylA3 ,CylA4 ,CylA5
                 ,CylA6 ,CylB1 ,CylB2 ,CylB3 ,CylB4 ,CylB5 ,CylB6 ,ActPwr ,kWhour ,Runhrs ,VRO)      
SELECT CONVERT(DATETIME,ItemDATE,103), ItemTIME, SITENAME, GENSETNAME, GENSET_SN, REASON, EVENT, RPM, Pwr
                 ,Gfrq ,Vg1 ,Vg2 ,Vg3 ,Vg12 ,Vg23 ,Vg31, Ig1, Ig2, Ig3, Mfrq, Vm1, Vm2, Vm3
                 ,Vm12 ,Vm23 ,Vm31 ,BIN ,BOUT ,Mode ,CCpres ,OilLev
                 ,ActDem ,OilT ,AirInT ,RecAT ,JWTout ,JWTin ,JWGKin ,CylA1 ,CylA2 ,CylA3 ,CylA4 ,CylA5
                 ,CylA6 ,CylB1 ,CylB2 ,CylB3 ,CylB4 ,CylB5 ,CylB6 ,ActPwr ,kWhour ,Runhrs ,VRO
FROM tmpDATA

但正如您所见,我复制的列是固定的,那么如果我的一个 .CSV 文件有一个列“HeatMeter”,我将如何将该列复制到 RTCU 表中?

提前致谢!! 尼尔

【问题讨论】:

如果您的目标表没有该字段,则无法将该字段插入到表中。对于要插入字段的数据,该字段必须存在。那么,您是在问如何将字段添加到现有表中吗?或者您是在问如何将table1.fieldX 插入table2.fieldY?目前的问题是How do I fit this square peg in this round hole?,但我认为我们需要更清楚地了解您的需求,以了解哪种方法实际上可以帮助您。 目标表将有该列,但源表可能有也可能没有该列。例如,源 A 可能有“Pwr, RPM, Volts, Freq, Mode”列,其中源 B 可能有“Pwr, RPM, Volts, Freq, Mode, CCpres, OilLev”,结果 A+B 将有“Pwr, RPM” , Volts, Freq, Mode, CCpres, OilLev' 那么如何确保将 Source A 和 B 的不同内容复制到结果中? 【参考方案1】:

我不能 100% 确定我了解您的需求,但这是我的最佳猜测...

你有一个目标表...

 ID | val_1 | val_2 | val_3

你有一个源表...

 ID | val_1 | val_3

您还有第二个源表...

 ID | val_2 | val_3

您想将来自两个不同来源的数据插入到目标表中......

一种选择是在不同的列上指定默认值...

CREATE TABLE destination (
  id      INT,
  val_1   INT DEFAULT(-1),
  val_2   INT DEFAULT(-2),
  val_3   INT DEFAULT(-3)
)

-- val3 is not specified in this insert
-- This means that it will appear as -3 for all the inserted rows
------------------------------------------------------------------
INSERT INTO destination (id, val_1, val_2)
SELECT id, val_1, val_2 FROM source1

-- val1 is not specified in this insert
-- This means that it will appear as -1 for all the inserted rows
------------------------------------------------------------------
INSERT INTO destination (id, val_2, val_3)
SELECT id, val_2, val_3 FROM source2

另一种选择是简单地硬编码您希望在“缺失”字段中显示的值...

-- source1 does not have a val_3 field, so we hard-code the insert
-- to always put NULL in that field.
-------------------------------------------------------------------
INSERT INTO destination (id, val_1, val_2, val3)
SELECT id, val_1, val_2, NULL  FROM source1

-- source2 does not have a val_1 field, so we hard-code the insert
-- to always put 0 in that field.
-------------------------------------------------------------------
INSERT INTO destination (id, val_1, val_2, val_3)
SELECT id, 0,  val_2, val_3 FROM source2

任何值都可以用作默认值或硬编码值。

【讨论】:

Dems,我认为这不会起作用,因为源表将始终具有相同的名称 tmpDATA。此 tmpDATA 表是根据 CSV 文件中包含的内容动态创建的。因此,对于 CSV 中存在的每一列,都会在 tmpDATA 表中创建该列。在我的问题中,所有 CSV 都会有一些永远不会像上面那样改变的常见列,但也会有变量列可能存在也可能不存在于 tmpDATA 表中。如:INSERT INTO RTCU(ItemDATE, ItemTIME, Variable1) SELECT CONVERT(DATETIME,ItemDATE,103), ItemTIME, (IF EXISTS (Variable1)) FROM tmpDATA @NeilRutherford - 这就是为什么在上面的例子中有两个不同的插入语句。插入目标表时,代码必须指定哪些值在哪里。如果源模式每次都不一样,那么每次插入语句都必须不一样。您有三个基本选择: 1. 强制执行确保所有字段都存在于您的 CSV 中的规则(即使该值为空白)。 2. 每次收到文件时手动编写不同的插入语句。 3. 编写代码(用 sql 或其他语言)为您编写新的 SQL Insert 语句(称为动态 SQL)

以上是关于SQL 插入到存在列的位置的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中反透视表时获取值存在的列的位置

SQL Server 2014 - MainTable 和 TempTable - 如果不存在则插入其他更新

HSQLDB 如果不存在则插入,如果存在则更新

sql server如何如何从一个表中提取部分资讯插入到另一表中

SQL语句 存在就更新不存在就插入

mysql 插入列的SQL语句