2017-10-14 159 views
0

以下是表結構:如何保存自動生成的主鍵標識的外鍵列在同一個表

CREATE TABLE [User] (
     [Id] bigint identity(1,1) not null, 
     [FirstName] nvarchar(100) not null, 
     [LastName] nvarchar(100) not null, 
     [Title] nvarchar(5) null, 
     [UserName] nvarchar(100) not null, 
     [Password] nvarchar(100) not null,  
     [Inactive] bit null, 
     [Created] Datetime not null, 
     [Creator] bigint not null, 
     [Modified] DateTime null, 
     [Modifier] bigint null 
     CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
     (
      [Id] Asc 
     ) 
    ); 

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]')) 
    ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id]) 
GO 


INSERT INTO [User] (Creator) Values ([Id] ?) 

這是一個情況下表爲空,第一個用戶是要在表中添加。否則,我沒有問題。

如何在插入語句的同時在創建者列中插入Id?

+0

那麼,在您的標題,你說_foreign KEY_但有一個在你的代碼,你也沒有顯示的所有列你的表格[[Creator] [bigint] NOT NULL,',你可以[編輯](https://stackoverflow.com/posts/46743153/edit)你的問題並添加表格結構並解釋更多。 – Sami

+0

我添加了表格結構,我需要在創建者列中插入相同的Id值 –

+0

查看更新Furqan。 – Sami

回答

1

一種方法可能是使用序列而不是標識列。下面的腳本可以達到相同的目的:

CREATE SEQUENCE dbo.useridsequence 
    AS int 
    START WITH 1 
    INCREMENT BY 1 ; 
GO 

CREATE TABLE [User] (
     [Id] bigint DEFAULT (NEXT VALUE FOR dbo.useridsequence) , 
     [FirstName] nvarchar(100) not null, 
     [LastName] nvarchar(100) not null, 
     [Title] nvarchar(5) null, 
     [UserName] nvarchar(100) not null, 
     [Password] nvarchar(100) not null,  
     [Inactive] bit null, 
     [Created] Datetime not null, 
     [Creator] bigint DEFAULT NEXT VALUE FOR dbo.useridsequence , 
     [Modified] DateTime null, 
     [Modifier] bigint null 
     CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
     (
      [Id] Asc 
     ) 
    ); 

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]')) 
    ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id]) 
GO 


INSERT INTO [User] 
(
    -- Id -- this column value is auto-generated 
    FirstName, 
    LastName, 
    Title, 
    UserName, 
    [Password], 
    Inactive, 
    Created, 
    Creator, 
    Modified, 
    Modifier 
) 
VALUES 
(
    'Foo', 
    'Bar', 
    'Title', 
    'UserName ', 
    'Password', 
    0, 
    GETDATE(), 
    DEFAULT, 
    GETDATE(), 
    1 
) 

SELECT * FROM [User] AS u 

結果: enter image description here

0

簡短的回答是,你不能這樣做。我建議你的模型首先在邏輯上是有缺陷的。您是否打算將[用戶]中的所有實際數據庫用戶(例如,創建用戶...用於登錄...)定義爲行?你需要考慮這一點 - 但典型的答案是否定的。如果答案是肯定的,那麼你完全不需要創建者列,因爲它是多餘的。所有你需要的是創建的日期 - 你可能應該定義一個默認值。

但是,如果你想這樣做,你需要分兩步來完成(你需要使列可以爲空)。您爲「真實」數據列插入一行(或多行)值。然後使用爲id生成的標識值更新這些相同的行。一個例子顯示了不同的方式來做到這一點

use tempdb; 
set nocount on; 
CREATE TABLE dbo.[user] (
     [user_id] smallint identity(3,10) not null primary key, 
     [name] nvarchar(20) not null, 
     [active] bit not null default (1), 
     [created] Datetime not null default (current_timestamp), 
     [creator] smallint null 
    ); 
ALTER TABLE dbo.[user] ADD CONSTRAINT [fk_user] FOREIGN KEY(creator) REFERENCES dbo.[user](user_id); 
GO 
-- add first row 
insert dbo.[user] (name) values ('test'); 
update dbo.[user] set creator = SCOPE_IDENTITY() where user_id = SCOPE_IDENTITY() 

-- add two more rows 
declare @ids table (user_id smallint not null); 
insert dbo.[user] (name) output inserted.user_id into @ids 
values ('nerk'), ('pom'); 
update t1 set creator = t1.user_id 
from @ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id; 
select * from dbo.[user] order by user_id; 

-- mess things up a bit 
delete dbo.[user] where name = 'pom'; 

-- create an error, consume an identity value 
insert dbo.[user](name) values (null); 

-- add 2 morerows 
delete @ids; 
insert dbo.[user] (name) output inserted.user_id into @ids 
values ('nerk'), ('pom'); 
update t1 set creator = t1.user_id 
from @ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id; 

select * from dbo.[user] order by user_id; 
drop table dbo.[user]; 

而且我改變了身份規範,以演示一些開發人員意識到的東西。它並不總是被定義爲(1,1),並且下一個插入的值可能由於多種原因跳轉 - 例如錯誤和緩存/重新啓動。最後,我認爲你會後悔用一個保留字命名錶,因爲引用它將需要使用分隔符。減輕痛苦。