I created a trigger that performs a check and automatically populates data into 2 tables. Only what happens the following error :
IDENTITY_INSERT is already ON for table 'X'. Cannot perform SET operation for table 'Y'.
I found this while researching the error:
"At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.”
So the fix was easy:
SET IDENTITY_INSERT Table1 ON -- insert statements for table1 SET IDENTITY_INSERT Table1 OFF SET IDENTITY_INSERT Table2 ON -- insert statements for table2 SET IDENTITY_INSERT Table2 OFF SET IDENTITY_INSERT Table3 ON -- insert statements for table3 SET IDENTITY_INSERT Table3 OFF
But as the data is populated via trigger is not possible to do so.
Does anyone have a solution to my problem please?
I apologize.
Thank you all.
Trigger-----
CREATE TRIGGER Alert ON registos AFTER INSERT AS BEGIN DECLARE @comp decimal = 0 DECLARE @id_sensores_em_alerta decimal DECLARE @tempmin decimal = 0 DECLARE @current_max_idAlarme int = (SELECT MAX(IdAlarme) FROM alarmes) DECLARE @maxidAlarme int DECLARE @temp decimal = (SELECT s.lim_inf_temp from sensores s JOIN inserted i ON s.idSensor=i.idSensor ) -- Insert into alarmes from the inserted rows if temperature less than tempmin INSERT alarmes (IdAlarme, descricao_alarme,data_criacao, idRegisto) SELECT ROW_NUMBER() OVER (ORDER BY i.idRegisto) + @current_max_idAlarme, 'temp Error', GETDATE(), i.idRegisto FROM inserted AS i WHERE i.Temperatura < @temp SET @maxidAlarme = (SELECT MAX(IdAlarme) FROM alarmes) INSERT INTO sensores_tem_alarmes(idSensor,idAlarme,dataAlarme) SELECT i.idSensor, @maxidAlarme, GETDATE() FROM inserted i SET @comp += 1; SET @id_sensores_em_alerta=1; SET @id_sensores_em_alerta = (SELECT MAX(id_sensores_em_alerta) FROM sensores_em_alerta) INSERT INTO sensores_em_alerta(id_sensores_em_alerta, idSensor, idAlarme, data_registo, numerosensoresdisparados) SELECT @id_sensores_em_alerta, i.idSensor, @maxidAlarme, GETDATE(), @comp FROM inserted i end
DataBase----
If the value inserted is larger than the current identity value for the table, SQL Server automatically uses the new inserted value as the current identity value. The setting of SET IDENTITY_INSERT is set at execute or run time and not at parse time.
Answers. In a given session , you can have only one table's IDENTITY_INSERT property set to ON. You can use set IDENTITY_INSERT state (on/off) only at excute or run time.
IDENTITY_INSERT is a table property that allows you to insert explicit values into the column of table identifiers, i.e. into the column with IDENTITY. The value of the inserted identifier can be either less than the current value or more, for example, to skip a certain interval of values.
I had a similar problem but it did not involve table triggers. I was running a script that refreshes data for multiple tables and I hit a foreign key reference error.
According to MSDN:
At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.
To resolve this, I ran SET IDENTITY_INSERT [dbo].[table_name] OFF
for each table I was trying to insert into. Then I was able to refresh my tables again after I corrected the reference error.
Edit: I should also mention that you can just disconnect and then reconnect to reset your session.
Allow SQL Server to insert the identity values automatically for you. Since this is a trigger, there could multiple rows being inserted at a time. For one row inserts, you can use SCOPE_IDENTITY()
function (http://msdn.microsoft.com/en-us/library/ms190315.aspx) to retrieve the identity value of your last inserted row. However, since we could have multiple rows inserted in a trigger, we will use the OUTPUT
clause (http://msdn.microsoft.com/en-us/library/ms177564.aspx) to get back a list of the inserted IdAlarme
values for each idRegisto
.
I'm assuming that alarmes.IdAlarme
and sensores_em_alerta.id_sensores_em_alerta
are the two identity fields in this trigger. If that is the case, then this should work:
CREATE TRIGGER Alert ON registos AFTER INSERT AS BEGIN DECLARE @comp decimal = 0 DECLARE @id_sensores_em_alerta decimal DECLARE @tempmin decimal = 0 DECLARE @temp decimal = (SELECT s.lim_inf_temp from sensores s JOIN inserted i ON s.idSensor=i.idSensor ) DECLARE @tblIdAlarme TABLE (idRegisto int not null, IdAlarme int not null); -- Insert into alarmes from the inserted rows if temperature less than tempmin -- IdAlarme is identity field, so allow SQL Server to insert values automatically. -- The new IdAlarme values are retrieved using the OUTPUT clause http://msdn.microsoft.com/en-us/library/ms177564.aspx INSERT alarmes (descricao_alarme,data_criacao, idRegisto) OUTPUT inserted.idRegisto, inserted.IdAlarme INTO @tblIdAlarme(idRegisto, IdAlarme) SELECT descricao_alarme = 'temp Error', data_criacao = GETDATE(), i.idRegisto FROM inserted AS i WHERE i.Temperatura < @temp ; --It looks like this table needs a PK on both idSensor and idAlarme fields, or else you will get an error here -- if an alarm already exists for this idSensor. INSERT INTO sensores_tem_alarmes(idSensor,idAlarme,dataAlarme) SELECT i.idSensor, a.IdAlarme, dataAlarme = GETDATE() FROM inserted i INNER JOIN @tblIdAlarme a ON i.idRegisto = a.idRegisto ; --not sure what this is doing?? Will always be 1. SET @comp += 1; --id_sensores_em_alerta is an identity field, so allow SQL Server to insert values automatically INSERT INTO sensores_em_alerta(idSensor, idAlarme, data_registo, numerosensoresdisparados) SELECT i.idSensor, a.IdAlarme, data_registo = GETDATE(), numerosensoresdisparados = @comp FROM inserted i INNER JOIN @tblIdAlarme a ON i.idRegisto = a.idRegisto ; END
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With