我有一个源表,应将其转换为一个目标表。源表包含四列,其中包含传感器值。目标表应包含四行,其中包含单个传感器值,并在第一列中包含传感器编号- 源表中的每一行。换句话说,目标表将有四倍多的行。(我认为这称为归一化。至少,我认为将来使用更多或更少或不同的传感器会更加实用。)
更多背景信息进行解释。我已经成功地尝试了一个插入触发器,该触发器可以单行执行该操作:
CREATE TRIGGER dbo.temperatures_to_sensors ON dbo.Data AFTER INSERT AS BEGIN DECLARE @line_no TINYINT; SET @line_no = 2; -- hardwired for the production line DECLARE @UTC DATETIME; DECLARE @value1 FLOAT; DECLARE @value2 FLOAT; DECLARE @value3 FLOAT; DECLARE @value4 FLOAT; SELECT @UTC = CAST((CAST(LEFT(inserted.UTC, 16) AS FLOAT) - 2415020.5) AS DATETIME), @value1 = inserted.temperature_1, @value2 = inserted.temperature_2, @value3 = inserted.temperature_3, @value4 = inserted.temperature_4 FROM inserted; INSERT INTO dbo.line_sensor_values (UTC, line_no, sensor_no, sensor_value) VALUES (@UTC, @line_no, 1, @value1), (@UTC, @line_no, 2, @value2), (@UTC, @line_no, 3, @value3), (@UTC, @line_no, 4, @value4); END; GO
现在,我想一次从旧表初始化目标表。之后,触发器将继续填充值。
我的SQL不好。我试过了:
CREATE PROCEDURE dbo.init_line_sensor_values AS BEGIN DECLARE @line_no TINYINT; SET @line_no = 2; -- hardwired for the production line DECLARE @UTC DATETIME; DECLARE @value1 FLOAT; DECLARE @value2 FLOAT; DECLARE @value3 FLOAT; DECLARE @value4 FLOAT; INSERT INTO dbo.line_sensor_values (UTC, line_no, sensor_no, sensor_value) VALUES (@UTC, @line_no, 1, @value1), (@UTC, @line_no, 2, @value2), (@UTC, @line_no, 3, @value3), (@UTC, @line_no, 4, @value4) SELECT @UTC = CAST((CAST(LEFT(t.UTC, 16) AS FLOAT) - 2415020.5) AS DATETIME), @value1 = t.temperature_1, @value2 = t.temperature_2, @value3 = t.temperature_3, @value4 = t.temperature_4 FROM dbo.Data AS t; END; GO EXECUTE dbo.init_line_sensor_values GO
…但是失败了
无法将值NULL插入表‘1000574.dbo.line_sensor_values’的列’UTC’中;列不允许为空。INSERT失败。
显然,SELECT应该以不同的方式使用来填充INSERT。还是我必须使用循环?(创建的游标FETCH NEXT...和WHILE...)
SELECT
INSERT
FETCH NEXT...
WHILE...
更新
可以通过这种方式(简化)创建源表:
CREATE TABLE dbo.Data( UTC varchar(32) NOT NULL, temperature_1 float NULL, temperature_2 float NULL, temperature_3 float NULL, temperature_4 float NULL PRIMARY KEY CLUSTERED ( UTC ASC ) GO
目标表是通过以下方式创建的:
CREATE TABLE dbo.line_sensor_values ( UTC DATETIME NOT NULL, line_no TINYINT NOT NULL, -- line number: 1, 2, 3, etc. sensor_no TINYINT NOT NULL, -- sensor number: 1, 2, 3, etc. sensor_value float NULL, -- the measured value PRIMARY KEY CLUSTERED ( UTC ASC, line_no ASC, sensor_no ASC ) ) GO
谢谢您的帮助,彼得
INSERT INTO dbo.line_sensor_value (UTC, line_no, sensor_no, sensor_value) select UTC, line_no, sensor_no, temperature_1 as sensor_value from dbo.Data union select UTC, line_no, sensor_no, temperature_2 as sensor_value from dbo.Data union select UTC, line_no, sensor_no, temperature_3 as sensor_value from dbo.Data union select UTC, line_no, sensor_no, temperature_4 as sensor_value from dbo.Data