我有3个表:audioFormats,videoFormats和fileInfo。 我有一个事务,当我插入fileInfo表时,该插入包括来自audioFormats和videoFormats的FK。如果音频格式或视频格式不在这些表中,则会插入后面的表格,然后将生成的(或现有的)ID值插入到fileInfo中。
如果该值不存在,我如何有效地插入值,但是获取值的ID,无论它是否已经存在,或者仅使用SQL(可能是事务)重新插入。
我可以插入一个值,如果它尚不存在:
INSERT INTO audioformats (audioformat)
VALUES(@format)
WHERE NOT EXISTS (SELECT 1 FROM audioformats WHERE audioformat = @format)
我可以从插入中获取插入的ID:
INSERT INTO audioFormats (audioFormat)
VALUES ('Test')
SET @audioFormatId = SCOPE_IDENTITY()
如果没有插入,SCOPE_IDENTITY将不会给我ID值。 我可以执行标量查询以在可能的插入后获取标识,但似乎我应该能够使用最多一个SELECT和INSERT完成所有这些。
答案 0 :(得分:13)
您可以使用IF语句执行此操作
IF NOT EXISTS(SELECT TOP 1 1 FROM audioformats WHERE audioformat = @format)
BEGIN
INSERT INTO audioFormats (audioFormat)
VALUES ('Test')
SET @audioFormatId = SCOPE_IDENTITY()
END
ELSE
BEGIN
SELECT @audioFormatID = ID FROM audioformats WHERE audioformat = @format
END
或者你可以这样做:
INSERT INTO audioformats (audioformat)
SELECT @format
FROM audioFormats
WHERE NOT EXISTS (SELECT TOP 1 1 FROM audioformats WHERE audioformat = @format)
SELECT @audioFormatID = ID FROM audioformats WHERE audioformat = @format
答案 1 :(得分:4)
我将答案标记为正确,因为它与我的最终SQL最相似,但它并没有真正满足最多使用一个查询和一个插入的原始要求。以下是,我最终使用的是:
-- One select
SELECT @audioFormatId = id
FROM audioformats
WHERE audioformat = @audioFormat;
-- Optionally one insert
IF @audioFormatId IS NULL AND @audioFormat IS NOT NULL
BEGIN
INSERT INTO audioFormats (audioFormat)
VALUES (@audioFormat)
SET @audioFormatId = SCOPE_IDENTITY()
END
当大多数对查询的调用确实执行插入时,Hogan的答案可能会更快,因为IF NOT EXISTS查询比实际返回行的查询要快。
在大多数情况下值已经存在的情况下,我的可能会更快,因为那时只会产生一个查询(并且没有IF NOT EXISTS查询)。我怀疑无效检查是微不足道的。
答案 2 :(得分:3)
我认为您可以使用MERGE
。
这为您提供了无交易的解决方案。一些明亮的火花可能能够使用output
子句来改善这一点,以获得目标ID,但下面的工作正常。
我在下面添加了一个指向StackOverflow查询测试器的链接。
-- Merge example
-- Get ID of existing row or insert new row
-- Initialise unit test data
declare @AudioFormatId int;
declare @AudioFormat nvarchar(50)
declare @tblAudioFormats TABLE (AudioFormatId int identity, AudioFormat nvarchar(50) );
insert into @tblAudioFormats(AudioFormat) values ('MP3'), ('WAV');
-- set query criteria
set @AudioFormat = 'MP3' -- query below returns 1 - updating MP3
--set @AudioFormat = 'WAV' -- query below returns 2 - updating WAV
--set @AudioFormat = 'MIDI' -- query below returns 3 - inserting MIDI
-- Insert or update AudioFormat and return id of target audio format.
merge
@tblAudioFormats as Target
using
(select @AudioFormat as AudioFormat) as source(AudioFormat)
on
(source.AudioFormat = target.AudioFormat)
when matched then
update set @AudioFormatID = target.AudioFormatId
when not matched then
insert(AudioFormat) values (source.AudioFormat);
if @AudioFormatId is null set @AudioFormatId = scope_identity()
-- return ID of target audio format
select @AudioFormatId as TargetAudioFormatId
在此处运行此查询:Query StackOverflow link for sample
答案 3 :(得分:2)
如果audioFormats表具有自动增量IDENTITY(1,1)
PK,您可以通过简单的选择获得刚插入的ID:
SELECT MAX(ID) FROM audioFormats
修改强>
正如评论中所提到的,只有一个查询插入表中时,此方法才适用。
否则,您可以查看IDENT_CURRENT('table_name')函数。
IDENT_CURRENT返回为a生成的最后一个标识值 指定的表或视图。生成的最后一个标识值可以是 任何会议和任何范围。
答案 4 :(得分:2)