SQL选择或插入返回ID

时间:2012-02-26 22:10:36

标签: sql sql-server sql-server-2008

好吧,这里有一个快速的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

我没有测试最后一个声明,但我认为漫长的方式会是这样的。如果没有内置方式,如果有人可以简单地纠正该陈述,我会很感激(因为我确定它不完全正确)。

3 个答案:

答案 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 和表格内容大两行。