我已经搜索过此内容,但是出现该内容的主题往往会得到不了解该问题的人的解答。
采用以下语法:
SET IDENTITY_INSERT Table1 ON
您如何做更多这样的事情:
GET IDENTITY_INSERT Table1
我不想对数据库中的数据或设置做任何事情来获取此信息。谢谢!
我已经搜索过此内容,但是出现该内容的主题往往会得到不了解该问题的人的解答。
采用以下语法:
SET IDENTITY_INSERT Table1 ON
您如何做更多这样的事情:
GET IDENTITY_INSERT Table1
我不想对数据库中的数据或设置做任何事情来获取此信息。谢谢!
IDENTITY_INSERT
将关闭!如果您不清楚某个会话是否保持相同的会话,Google会话(不完全是=连接),请查看sys.dm_exec_sessions
和sys.dm_exec_connections
,或下载sp_WhoIsActive
和EXEC sp_WhoIsActive @show_sleeping_spids = 2, @show_own_spid = 1
Answers:
由于SET IDENTITY_INSERT
是对会话敏感的,因此可以在缓冲区级别对其进行管理,而无需存储在任何地方。这意味着我们不需要检查IDENTITY_INSERT
状态,因为我们在当前会话中从未使用过此关键字。
抱歉,对此没有帮助。
虽然是个好问题:)
资料来源:这里
更新 也许有一些方法可以做到这一点,在我链接的网站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
综上所述:
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
/的Bogdan Bodanov解决方案catch
也可以正常工作,但其他检查应将异常处理限制在以下情况下: IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';
您可以使用下面的代码发现是否启用了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
如果您想关闭其他表的IDENTITY_INSERT,以避免在想要将IDENTITY_INSERT设置为on时收到错误,则以下内容也可能对您有用。正如其他人在该线程上所说的那样,IDENTITY_INSERT是一个没有直接可见性的会话设置。但是,我做了一个有趣的发现,对于具有身份的任何表,无论该表的IDENTITY_INSERT是否为ON,SET IDENTITY_INSERT OFF都不会出错。因此,我想到可以对数据库中具有身份的每个表都调用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
IDENTITY_INSERT
在调用脚本中(或之前)调用了set on,则肯定是有原因的。:p假定呼叫者此后不再继续依赖该信息是错误的,并且可能有危险。在设计上明智的做法是,最好的恕我直言,只要尝试将其设置为任意状态,并在必要时让整个设备崩溃并燃烧即可。至少开发人员将了解发生了什么问题-假设错误记录在某处。
如果您想了解会话变量...是个好问题,但是我看不到该信息在哪里有用。在正常执行中检查对插入的正常表响应时,这应该起作用!
-如果只想知道给定表上是否存在标识插入:
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
玩得开心!
IDENTITY_INSERT
表是否具有身份列是否在上
is_identity
在列sys.columns
表确定该列是否是标识列或否,变量不是否IDENTITY_INSERT
是ON
或OFF
很好的问题。我有同样的问题。也许您可以尝试使用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
。
您还可以使用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
TableHasIdentity
表中定义的值的状态,而不是IDENTITY_INSERT
操作正在寻找的实际会话存储值。自己尝试:有一个查询来检查属性,然后更改IDENTITY_INSERT
表的值,然后再次获取对象属性。其值仍将与以前相同。
这是我的解决方案。它与@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