我已经搜索过这个,但出现它的线程往往会从不理解这个问题的人那里得到答案。
采用以下语法:
SET IDENTITY_INSERT Table1 ON
你如何做更多这样的事情:
GET IDENTITY_INSERT Table1
我不想对数据库中的数据或设置做任何事情来获取这些信息。谢谢!
我已经搜索过这个,但出现它的线程往往会从不理解这个问题的人那里得到答案。
采用以下语法:
SET IDENTITY_INSERT Table1 ON
你如何做更多这样的事情:
GET IDENTITY_INSERT Table1
我不想对数据库中的数据或设置做任何事情来获取这些信息。谢谢!
由于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
Ricardo 的解决方案允许更大的灵活性,但需要 Column 的身份名称
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U')
AND name = 'MyTableIdentityColumnName';
Bogdan Bodanov 解决方案,使用try
/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 时出现错误,以下可能也适用于您。正如其他人在这个线程上所说的那样 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
非常好的问题。我有同样的问题。也许您可以尝试使用 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
。
如果您想了解会话变量...好问题,但我看不出这些信息在哪里有用。在正常执行中检查对插入的正常表响应,这应该有效!
-- 如果您只想知道给定表上是否有标识插入:
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
玩得开心!
这是我的解决方案。这与@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
您还可以使用 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