好吧,这里有一个快速的SQL问题(使用sql-server-2008)。
我有一个映射表names
,其中包含以下列
ID
DisplayName
我想先做的是
SELECT [ID] FROM [names] WHERE [DisplayName] = 'chuck';
但是,如果数据库中不存在名称'chuck',我想创建它,并返回自动递增的ID
。
我想知道SQL是否有一些简单的内置方法,或者我是否需要走很长的路?
漫长的路线是这样的
SELECT COUNT(ID) AS count, ID FROM names WHERE DisplayName='chuck'
IF(count > 0)
SELECT ID as ReturnID;
ELSE
BEGIN
INSERT INTO names(DisplayName) values('chuck');
SELECT scope_identity() as ReturnID;
END
我没有测试最后一个声明,但我认为漫长的方式会是这样的。如果没有内置方式,如果有人可以简单地纠正该陈述,我会很感激(因为我确定它不完全正确)。
答案 0 :(得分:4)
你也应该关注交易:
set XACT_ABORT on
begin tran
declare @ID int
select @ID = ID from names with (holdlock, updlock) WHERE DisplayName='chuck'
if @@rowcount = 0
begin
INSERT INTO names(DisplayName) values('chuck');
set @ID = scope_identity();
end
select @ID as ReturnID;
commit tran
请注意表提示的使用 - holdlock 和 updlock 。它们阻止另一个线程执行完全相同的查询并再次创建该行。有关更多信息,请查找隔离,同步,死锁,并发更新。
答案 1 :(得分:0)
我愿意:
IF (NOT EXISTS(SELECT null from names where DisplayName='Chuck'))
INSERT INTO Names (DisplayName) Values ('Chuck')
SELECT ID as ReturnID FROM Names where DisplayName='Chuck'
虽然
但节省不多答案 2 :(得分:0)
go
create table names
(
Id int primary key identity(1,1),
displayname varchar(100),
);
go
create procedure P1
@displayname varchar(100)
as
insert into names (displayname)
select @displayname
where not exists (
select * from names, (select @displayname as displayname) as names2
where names.displayname = names2.displayname);
-- race condition is possible here,
-- but in some cases you still may get away with this
select id from names where displayname = @displayname;
go
declare @dn varchar(100);
set @dn = 'chuck'; exec P1 @dn; exec P1 @dn; exec P1 @dn;
set @dn = 'buck'; exec P1 @dn; exec P1 @dn;
select * from names;
go
drop table names; drop procedure P1;
输出将 1, 1, 1, 2, 2
和表格内容大两行。