你得到的错误是因为你试图插入一个标识列DoorNumber
:
DoorNum INT IDENTITY(1,1) PRIMARY KEY,
从列列表中删除该列,而不是:
INSERT INTO Prison_Doors(DoorNum,DoorOpen,DoorClosed)
删除该列DoorNum
:
INSERT INTO Prison_Doors(DoorOpen,DoorClosed)
...
但是,不需要动态 SQL 来执行此操作,您可以使用如下锚表执行此操作:
WITH temp
AS
(
SELECT n
FROM (VALUES(1), (2), (3), (4)) temp(n)
), nums
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS n
FROM temp t1, temp t2, temp t3
)
INSERT INTO Prison_Doors(DoorOpen, DoorClosed)
SELECT 0 AS DoorOpen, 1 AS DoorClosed
FROM nums
WHERE n <= 50;
更新:
我的代码逐行做什么?
生成数字序列:
第一个问题是生成从 1 到 50 的 50 个数字的序列,我使用了一个只有四行从 1 到 4 的锚表,如下所示:
SELECT n
FROM (VALUES(1), (2), (3), (4)) temp(n);
这种使用 SQL-Server-2008 的语法VALUES
是新的,它被称为行值构造函数。在 之后VALUES
,您分配表的别名和括号中的目标列,例如temp(n)
。
对于旧版本,您必须使用类似的东西:
SELECT n
FROM
(
SELECT 1 AS n
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
) AS temp;
这将只给你 4 行,但我们需要生成 50 行。这就是为什么我CROSS JOIN
这个表使用了 3 次:
FROM temp t1, temp t2, temp t3
它与
FROM temp t1
CROSS JOIN temp t2
CROSS JOIN temp t3
这会将这些行乘以 64 次,4 行3 = 64 行:
1 1 1
1 2 1
1 3 1
1 4 1
2 1 1
2 2 1
2 3 1
2 4 1
....
3 1 4
3 2 4
3 3 4
3 4 4
4 1 4
4 2 4
4 3 4
4 4 4
功能的使用ROW_NUMBER()
:
然后使用ROW_NUMBER()
会给我们一个从 1 到 64 的排名数字,如下所示:
WITH temp
AS
(
SELECT n
FROM (VALUES(1), (2), (3), (4)) temp(n)
)
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS n
FROM temp t1, temp t2, temp t3;
请注意:ROW_NUMBER
需要一个ORDER BY
子句,否则顺序无关紧要,所以我使用了(SELECT 1)
.
还有另一种不使用 来生成序列号的方法ROW_NUMBER
,它也取决于CROSS JOIN
,具有如下锚表:
WITH temp
AS
(
SELECT n
FROM (
VALUES(0), (1), (2), (3), (4), (5), (6), (7), (8), (9)
) temp(n)
), nums
AS
(
SELECT t1.n * 100 + t2.n * 10 + t3.n + 1 AS n
FROM temp t1, temp t2, temp t3
)
SELECT n
FROM nums
ORDER BY n;
另一种生成数字序列的方法
常用表表达式:
CTE称为通用表表达式,在SQL Server 2005中引入,是SQL Server支持的表表达式类型之一。其他三个是:
它有很多重要的优点。其中之一是让您创建一个虚拟表,以后可以重复使用它们,就像我所做的那样:
WITH temp
AS
(
SELECT n
FROM (VALUES(1), (2), (3), (4)) temp(n)
), nums
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS n
FROM temp t1, temp t2, temp t3
)
...
在这里,我定义了两个 CTE ,temp
然后定义了另一个nums
,temp
所以这个 OL,你可以创建多个 CTE,只需放一个分号,然后是一个带有AS
子句和两个的新 CTE ()
。
使用从另一个表插入一个表INSERT INTO ... SELECT ...
现在,我们有一个nums
从 1 到 64 行的虚拟表,我们需要插入从 1 到 50 的行。
为此,您可以使用INSERT INTO ... SELECT ...
.
请注意,INSERT
子句中的列是可选的,但是如果这样做,则必须为每一行输入一个值,否则会出现错误,例如,如果您有四列,而VALUES
子句中只输入了三个值或者在SELECT
子句中,那么你会得到一个错误。这对于定义如下的 idenetityt 列无效:
Identity(1,1)
^ ^
| |
| ------------------The seed
The start
在这种情况下,您只需忽略子句中列列表中的该列INSERT
,它将具有标识值。有一个选项可以让您手动插入一个值,就像在@Raj's answer中一样。
请注意:在我的回答中,我没有将序列号插入该列,而是将值插入 50 次。但是由于 Identity 列,实际数字会自动生成:
...
INSERT INTO Prison_Doors(DoorOpen, DoorClosed)
SELECT 0 AS DoorOpen, 1 AS DoorClosed
FROM nums;
WHERE n <= 50;