web-dev-qa-db-ja.com

外部キー関係を持つ2つのテーブルに値を挿入する方法は?

2つのテーブルを作成しました。

  • テーブルtblStaffカラムid(主キー、自動インクリメント)、nameageaddress

  • テーブルtblRoleOfStaffid(主キー、自動インクリメント)、StaffIdtblStaffへの外部キー)、RoleId

既存の役割を持つ新しいスタッフを作成するフォームがあります。挿入するデータサンプル:

(name, age, address, roleId) = ('my name',20,'San Jose', 1)

新しいスタッフをtblStaffに挿入し、tbleRoleOfStaffに挿入したばかりのstaffIdに新しいレコードを挿入するストアドプロシージャをSQL Server 2014で作成します。

私は何をすべきか?

私の質問が他の質問と重複している場合、とても申し訳ありません。私はSQLの方が新鮮です。助けてくれてありがとう。

9
Ca Pham Van

SCOPE_IDENTITY()tblRoleOfStuffの場所のStaffIdへの2番目の挿入を使用します。お気に入り:

_insert into tblStaff values
(@name, @age, @address)

insert into tblRoleOfStuff values
(scope_identity(), @roleid)
_

[〜#〜] edit [〜#〜]

この答えに対するコメントが多すぎるので、説明したいと思います。

OPが_@@IDENTITY_(悪い習慣)を使用する可能性のあるトリガーを使用しないことを保証する場合、彼のニーズには十分ですが、SCOPE_IDENTITY()を使用することをお勧めします。

@@ IDENTITYのようなSCOPE_IDENTITY()は、現在のセッションで作成された最後のID値を返しますが、現在のスコープにも制限します。つまり、トリガーまたはユーザー定義関数によって作成されたIDではなく、明示的に作成した最後のID値を返します。

SCOPE_IDENTITY()は、別の接続または最後に処理された接続からではなく、現在の操作からIDを取得することを保証します。

なぜ_IDENT_CURRENT_ではありませんか?なぜなら

IDENT_CURRENTはスコープとセッションによって制限されません。指定されたテーブルに制限されます。 IDENT_CURRENTは、任意のセッションおよび任意のスコープの特定のテーブルに対して生成されたID値を返します。

したがって、最後にスコープされたが、現在のものではありません。はい、OPでも使用できますが、そのような状況では悪い習慣です(_@@IDENTITY_のみを使用するなど)

OUTPUTを使用するのは確かに良い方法ですが、1つのIDだけでは複雑すぎます。 OPが一度に複数の行を処理する必要がある場合-はい、彼はOUTPUTを必要とします。

12
gofr1

最初のinsertステートメントからoutputを使用できます。

declare @tmp table(id int)
insert tblStaff (name, age, address)
OUTPUT inserted.Id INTO @tmp (id)
values (@name, @age, @address)

declare @roleId int = 1 --or whatever
insert tblRoleOfStaff (staffId,roleId)
select id, @roleId
from @tmp

複数のロールを一度に挿入することもできます。

create table Roles (roleId int identity(1,1) primary key, 
RoleName varchar(50),
isDefaultRole bit default 0
)
--mark some roles as default (`isDefaultRole = 1`)
--the 2nd insert will be
insert tblRoleOfStaff (staffId,roleId)
select id, roleId
from @tmp
cross join Roles
where isDefaultRole = 1
2
Alex Kudryashev