【问题标题】:Auto Increment : SQL Server自动增量:SQL Server
【发布时间】:2021-01-07 21:20:53
【问题描述】:

我有一个表 (Table1),其中一个 auto_increment ID 列作为主键,它运行良好。我还有另一个表 (Table2),其外键使用 Table1 中的 ID 列。

现在,当我查看 Table2 中的记录时,我在 ID 列中看到了 NULL,但我没有得到自动生成的数字。我也尝试了Identity(1,1) 并看到了相同的结果。

我该如何解决这个问题?

作为后续,假设我向现有表中添加了一个新列,并希望为其赋予 1 到 20 的值。我该怎么做?

【问题讨论】:

  • 外键不会自动填充值。这并不总是一对一的关系。通常,Table1 中的每一行都会被 Table2 中的许多(或没有)行引用。您希望数据库如何知道 Table1 中的哪个 ID 值与 Table2 中的每条记录一起使用?对于第二部分,如果您的表超过 20 行,您想做什么?
  • IF 外键被定义为IDENTITY(这是一个真的坏主意),然后它也不会有NULL 值。

标签: sql-server sql-update auto-increment alter generic-foreign-key


【解决方案1】:

正如 Joel 所提到的,约束值不会自动从一个表插入到另一个表。如果 Table2 中的外键是 Table1 中的主键值,那么在向@Table2 插入新行之前,您需要捕获@Table1 的主键值。

这是执行此操作的常用方法。您可以在 SSMS 中运行此示例。

/* Create a mock-up of Table1 and Table2 */
DECLARE @Table1 TABLE ( 
    Table1_Value VARCHAR(50), pk_Table1 INT IDENTITY (1,1) NOT NULL PRIMARY KEY 
);

DECLARE @Table2 TABLE ( 
    fk_Table1 INT, Table2_Value VARCHAR(50), pk_Table2 INT IDENTITY (999,1) NOT NULL PRIMARY KEY 
);

声明一个表变量 (@out) 以在插入行时捕获 Table1 的主键值:

/* Declare an OUTPUT table to capture the PK of the value inserted into @Table1 */
DECLARE @out TABLE ( pk_Table1 INT );

一旦我们有了这些东西,我们就可以在 Table1 中插入一个新行并捕获它的主键值。

/* Insert a value into @Table1 and capture its PK */
INSERT INTO @Table1 ( Table1_Value ) 
OUTPUT inserted.pk_Table1 INTO @out
VALUES
    ( 'Table1_Value01' );

值得注意的是这个人:

OUTPUT inserted.pk_Table1 INTO @out

这允许我们捕获插入到 Table1 中的任何值,但在这种情况下,我们关心的是 pk_Table1

如果我们查看@out的结果集:

/* Show the results captured in @out */
SELECT * FROM @out;

我们看到以下内容:

+-----------+
| pk_Table1 |
+-----------+
|         1 |
+-----------+

查看@Table1的结果集:

/* Show the @Table1 resultset */
SELECT * FROM @Table1 ORDER BY pk_Table1;

返回:

+----------------+-----------+
|  Table1_Value  | pk_Table1 |
+----------------+-----------+
| Table1_Value01 |         1 |
+----------------+-----------+

现在我们已经捕获了 Table1 新行的主键,我们可以将一个新行插入到 @Table2 中,其值将其与 @Table1 联系起来。

/* Insert a new value into @Table2 with a foreign key value pointing to @Table1 */
INSERT INTO @Table2 ( fk_Table1, Table2_Value )
    VALUES ( ( SELECT pk_Table1 FROM @out ), 'Table2 value related to Table1 value.' );

这家伙……

( SELECT pk_Table1 FROM @out )

返回我们在将行插入@Table1 时捕获的主键值。

如果我们查看@Table2的结果集:

/* Show the @Table2 resultset */
SELECT * FROM @Table2 ORDER BY pk_Table2;

我们看到了:

+-----------+---------------------------------------+-----------+
| fk_Table1 |             Table2_Value              | pk_Table2 |
+-----------+---------------------------------------+-----------+
|         1 | Table2 value related to Table1 value. |       999 |
+-----------+---------------------------------------+-----------+

最后,我们可以根据它们的关系将两个表连接在一起:

/* Join the two tables based on their relationship */
SELECT
    t1.pk_Table1,
    t1.Table1_Value,
    t2.fk_Table1,
    t2.pk_Table2,
    t2.Table2_Value
FROM @Table1 AS t1
INNER JOIN @Table2 AS t2
    ON t1.pk_Table1 = t2.fk_Table1
ORDER BY
    t1.pk_Table1;

返回:

+-----------+----------------+-----------+-----------+---------------------------------------+
| pk_Table1 |  Table1_Value  | fk_Table1 | pk_Table2 |             Table2_Value              |
+-----------+----------------+-----------+-----------+---------------------------------------+
|         1 | Table1_Value01 |         1 |       999 | Table2 value related to Table1 value. |
+-----------+----------------+-----------+-----------+---------------------------------------+

显然,这不是深入探讨基于唯一值关联两个表,但是,它很容易理解。

这是您可以在 SSMS 中运行的完整示例:

/* Create a mock-up of Table1 and Table2 */
DECLARE @Table1 TABLE ( 
    Table1_Value VARCHAR(50), pk_Table1 INT IDENTITY (1,1) NOT NULL PRIMARY KEY 
);

DECLARE @Table2 TABLE ( 
    fk_Table1 INT, Table2_Value VARCHAR(50), pk_Table2 INT IDENTITY (999,1) NOT NULL PRIMARY KEY 
);

/* Declare an OUTPUT table to capture the PK of the value inserted into @Table1 */
DECLARE @out TABLE ( pk_Table1 INT );

/* Insert a value into @Table1 and capture its PK */
INSERT INTO @Table1 ( Table1_Value ) 
OUTPUT inserted.pk_Table1 INTO @out
VALUES
    ( 'Table1_Value01' );

/* Show the results captured in @out */
SELECT * FROM @out;

/* Show the @Table1 resultset */
SELECT * FROM @Table1 ORDER BY pk_Table1;

/* Insert a new value into @Table2 with a foreign key value pointing to @Table1 */
INSERT INTO @Table2 ( fk_Table1, Table2_Value )
    VALUES ( ( SELECT pk_Table1 FROM @out ), 'Table2 value related to Table1 value.' );

/* Show the @Table2 resultset */
SELECT * FROM @Table2 ORDER BY pk_Table2;

/* Join the two tables based on their relationship */
SELECT
    t1.pk_Table1,
    t1.Table1_Value,
    t2.fk_Table1,
    t2.pk_Table2,
    t2.Table2_Value
FROM @Table1 AS t1
INNER JOIN @Table2 AS t2
    ON t1.pk_Table1 = t2.fk_Table1
ORDER BY
    t1.pk_Table1;

【讨论】:

    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    相关资源
    最近更新 更多