我已经搜索了这个,但是它出现的主题往往会得到那些不理解这个问题的人的答案。
采用以下语法:
SET IDENTITY_INSERT Table1 ON
你怎么做更像这样的事情:
GET IDENTITY_INSERT Table1
我不想对数据库中的数据或设置做任何事情来获取此信息。谢谢!
答案 0 :(得分:30)
由于SET IDENTITY_INSERT
是会话敏感的,因此它在缓冲级别进行管理而不存储在某处。这意味着我们无需检查IDENTITY_INSERT
状态,因为我们从未在当前会话中使用此关键字。
抱歉,没有帮助。
但很好的问题:)
来源:Here
<强>更新强> 有很多方法可以做到这一点,也可以在我链接的网站上看到,IMO,它太费力了。
if
(select max(id) from MyTable) < (select max(id) from inserted)
--Then you may be inserting a record normally
BEGIN
set @I = 1 --SQL wants something to happen in the "IF" side of an IF/ELSE
END
ELSE --You definitely have IDENTITY_INSERT on. Done as ELSE instead of the other way around so that if there is no inserted table, it will run anyway
BEGIN
.... Code that shouldn't run with IDENTITY_INSERT on
END
答案 1 :(得分:16)
总结:
Nathan的解决方案是最快的:
SELECT OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity');
使用API包装器时,可以将整个检查减少到只检查行。例如,当使用C#的SqlDataReaders
属性HasRows
和查询结构时:
SELECT CASE OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity')
WHEN 1 THEN '1' ELSE NULL END
里卡多的解决方案允许更灵活,但需要列的身份名称
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U')
AND name = 'MyTableIdentityColumnName';
使用try
/ catch
的Bogdan Bodanov解决方案也可以使用,但是其他检查应该将异常处理限制在IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';
答案 2 :(得分:6)
如果您尝试为某个其他表关闭IDENTITY_INSERT以避免在您要设置IDENTITY_INSERT时出现错误,则以下内容也适用于您。正如其他人在此主题中所说,IDENTITY_INSERT是一个没有直接可见性的会话设置。但是我做了一个有趣的发现,SET IDENTITY_INSERT OFF对于任何具有标识的表都不会出错,无论该表的IDENTITY_INSERT是否为ON。所以我想到我可以为数据库中具有标识的每个表调用SET IDENTITY_INSERT ... OFF。感觉有点像蛮力解决方案,但是 我发现以下动态SQL块非常好地完成了这个技巧。
---- make sure IDENTITY_INSERT is OFF ----
DECLARE @cmd NVARCHAR(MAX)
SET @cmd = CAST((SELECT 'SET IDENTITY_INSERT ' +
QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' +
QUOTENAME(t.name) + ' OFF' + CHAR(10)
FROM sys.columns c
JOIN sys.tables t ON t.object_id = c.object_id
WHERE c.is_identity = 1
ORDER BY 1 FOR XML PATH('')) AS NVARCHAR(MAX))
EXEC sp_executesql @cmd
答案 3 :(得分:6)
您可以发现identity_insert是否已启用,如果是,则使用以下代码查找哪个表。
declare @tableWithIdentity varchar(max) = '';
SET IDENTITY_INSERT ExampleTable ON
begin try
create table #identityCheck (id int identity(1,1))
SET IDENTITY_INSERT #identityCheck ON
drop table #identityCheck
end try
begin catch
declare @msg varchar(max) = error_message()
set @tableWithIdentity= @msg;
set @tableWithIdentity =
SUBSTRING(@tableWithIdentity,charindex('''',@tableWithIdentity,1)+1, 10000)
set @tableWithIdentity = SUBSTRING(@tableWithIdentity,1, charindex('''',@tableWithIdentity,1)-1)
print @msg;
drop table #identityCheck
end catch
if @tableWithIdentity<>''
begin
print ('Name of table with Identity_Insert set to ON: ' + @tableWithIdentity)
end
else
begin
print 'No table currently has Identity Insert Set to ON'
end
答案 4 :(得分:3)
如果你想了解会话变量......很好的问题,但我不知道这些信息在哪里有用。在正常执行中检查对插入的正常表响应,这应该有效!
- 如果您只想知道给定表上是否有标识插入:
select is_identity
from sys.columns
where object_id = OBJECT_ID('MyTable', 'U') and name = 'column_Name'
- 或者...如果您想根据结果执行某些操作,请使用此选项:
if exists (select *
from sys.columns
where object_id = OBJECT_ID('MyTable', 'U') and is_identity = 1)
... your code considering identity insert
else
... code that should not run with identity insert
玩得开心!
答案 5 :(得分:1)
非常好的问题。我有同样的问题。也许你可以尝试使用TRY / CATCH重置IDENTITY_INSERT?例如,您创建作业但不确定作业是否已完成且IDENTITY_INSERT设置为OFF。
为什么你不试试:
BEGIN TRY
...
END TRY
BEGIN CATCH
SET IDENTITY_INSERT table OFF;
END CATCH;
此外,我不确定这是否正常,但我发现只添加SET IDENTITY_INSERT ... OFF
没有返回错误。因此,您可以在最后设置SET IDENTITY_INSERT ... OFF
。
答案 6 :(得分:0)
您还可以使用ObjectProperty方法来确定表是否具有标识:
DECLARE @MyTableName nvarchar(200)
SET @MyTableName = 'TestTable'
SELECT CASE OBJECTPROPERTY(OBJECT_ID(@MyTableName), 'TableHasIdentity')
WHEN 1 THEN 'has identity'
ELSE 'no identity columns'
END as HasIdentity
答案 7 :(得分:0)
这是我的解决方案。这与@jmoreno的答案非常相似。
您会这样称呼它
DECLARE @IdentityInsert VARCHAR(20)
EXEC dbo.GetIdentityInsert 'YourDb', 'YourSchema', 'YourTable', @IdentityInsert OUT
SELECT @IdentityInsert
这将返回具有列名IDENTITY_INSERT的1行记录集,该记录集可以为ON,OFF或NO_IDENTITY(如果给定表没有标识列)。它还设置输出参数@IdentityInsert。因此,您可以将代码调整为您喜欢的任何一种方法。
将其引入用户定义的函数中会很好,但是不幸的是,我找不到避免TRY..CATCH块的方法,您无法在用户定义的函数中使用它。
-- ================================================================================
-- Check whether the table specified has its IDENTITY_INSERT set to ON or OFF.
-- If the table does not have an identity column, NO_IDENTITY is returned.
-- Tested on SQL 2008.
-- ================================================================================
CREATE PROCEDURE dbo.GetIdentityInsert
@dbname sysname
, @schemaname sysname
, @table sysname
, @IdentityInsert VARCHAR(20) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @OtherTable nvarchar(max)
DECLARE @DbSchemaTable nvarchar(max)
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
DECLARE @ErrorNumber INT;
DECLARE @object_id INT;
SET @DbSchemaTable = @dbname + '.' + @schemaname + '.' + @table
SET @object_id = OBJECT_ID(@DbSchemaTable)
IF @object_id IS NULL
BEGIN
RAISERROR('table %s doesn''t exist', 16, 1, @DbSchemaTable)
RETURN
END
BEGIN TRY
SET @object_id = OBJECT_ID(@DbSchemaTable)
IF OBJECTPROPERTY(@object_id,'TableHasIdentity') = 0
BEGIN
SET @IdentityInsert = 'NO_IDENTITY'
END
ELSE
BEGIN
-- Attempt to set IDENTITY_INSERT on a temp table. This will fail if any other table
-- has IDENTITY_INSERT set to ON, and we'll process that in the CATCH
CREATE TABLE #GetIdentityInsert(ID INT IDENTITY)
SET IDENTITY_INSERT #GetIdentityInsert ON
SET IDENTITY_INSERT #GetIdentityInsert OFF
DROP TABLE #GetIdentityInsert
-- It didn't fail, so IDENTITY_INSERT on @table must set to OFF
SET @IdentityInsert = 'OFF'
END
END TRY
BEGIN CATCH
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorNumber = ERROR_NUMBER();
IF @ErrorNumber = 8107 --IDENTITY_INSERT is already set on a table
BEGIN
SET @OtherTable = SUBSTRING(@ErrorMessage, CHARINDEX(char(39), @ErrorMessage)+1, 2000)
SET @OtherTable = SUBSTRING(@OtherTable, 1, CHARINDEX(char(39), @OtherTable)-1)
IF @OtherTable = @DbSchemaTable
BEGIN
-- If the table name is the same, then IDENTITY_INSERT on @table must be ON
SET @IdentityInsert = 'ON'
END
ELSE
BEGIN
-- If the table name is different, then IDENTITY_INSERT on @table must be OFF
SET @IdentityInsert = 'OFF'
END
END
ELSE
BEGIN
RAISERROR (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState);
--THROW Use this if SQL 2012 or higher
END
END CATCH
SELECT [IDENTITY_INSERT] = @IdentityInsert
END
GO