How do I write the following code in ScalikeJDBC QueryDSL, or in the most elegant way available through ScalikeJDBC?
begin tran
if not exists (select * from T1 with (UPDLOCK) where c1=1 and c2=2 )
insert into T1(c1,c2) values(1,2)
commit tran
Related
I am adding a trigger to an existing database table, which is used by an application I did not code, and cannot change the code in.
I want to insert some information from TableA into TableB on INSERT into TableA.
Application runs INSERT INTO TableA <-- this updates ##identity
An ON INSERT trigger that runs on TableA then inserts data into TableB <-- this also updates the ##identity with a new value
Application reads ##identity <-- which is from TableB not from TableA as the application is expecting
Is there any way to not update the ##identity from within the trigger?
....since ##identity has no scope you could create your own scope which carries the ##identity value at the end of the trigger
create table tableA(idA int identity(100, 1), colA int)
go
create table tableB(idB int identity(1000, 1), colB int)
go
create trigger triggerA on tableA
for insert
as
begin
if not exists(select * from inserted)
begin
return;
end
declare #tableA##identity int = ##identity;
select ##identity as [##identity_triggerA_in];
--add rows to tableB
insert into tableB(colB)
select object_id
from sys.all_objects
select ##identity as [##identity_after_insert_in_tableB];
if #tableA##identity is not null
begin
declare #sql varchar(100) = concat('create table #t(id int identity(', #tableA##identity, ',1)); insert into #t default values');
exec (#sql);
end
select ##identity as [##identity_triggerA_out];
end
go
insert into tableA(colA) values (10);
select ##identity;
go
insert into tableA(colA)
select top (200) 1
from sys.all_objects;
select ##identity;
go
insert into tableA(colA)
select 1
where 1=2;
select ##identity;
go
drop table tableA;
go
drop table tableB;
go
I have 3 tables:
transaction(IDtransaction,IDperson,IDPos,IDStore,TotalValue,Date)
items(IDtransaction,IDItem,IDproduct,Quantity)
persons(IDperson, balance)
What I am trying to accomplish is to delete from transaction when the total value is bigger that the balance of that person however it doesn't seem to work when I insert at the same time a wrong and a correct record. Why isn't working?
create trigger trigger4
on transaction
After insert,update
As
BEGIN
delete transaction
FROM inserted i
where transaction.IDtransaction=i.IDtransaction AND EXISTS (select * from inserted i, persons p
where i.IDperson=p.IDperson
and i.TotalValue > p.balance)
if ##ROWCOUNT > 0
begin
print('Error!')
if exists(select 1 from deleted) and exists (select 1 from inserted) --check if it is an update
begin
SET IDENTITY_INSERT transaction ON
insert into transaction(IDtransaction,IDperson,IDPos,IDStore,TotalValue,Date)
select d.IDtransaction,d.IDperson,d.IDPos,d.IDStore,d.TotalValue,d.Date
from deleted d
where d.IDtransaction not in (select t.IDtransaction from transaction t)
SET IDENTITY_INSERT transaction OFF
end
end
END
I'm a little surprised that this doesn't throw a syntax error, but this bit is wrong:
delete transaction
FROM inserted i
where transaction.IDtransaction=i.IDtransaction AND EXISTS (select * from inserted i, persons p
where i.IDperson=p.IDperson
and i.TotalValue > p.balance)
Because you aren't joining inserted to transaction so the DELETE isn't correlated to the FROM.
I am using SQL Transaction and inside transaction I need to insert multiple record in one go.
But problem is that my Id is not identity. So, I need to get max id and insert it.
But when I get the max and increment +1. It is always same.
Following is the my code.
BEGIN
DECLARE #maxId INT;
SET #maxId = (SELECT MAX(id) FROM [dbo].[tempUser]);
BEGIN TRAN
BEGIN TRY
INSERT INTO [dbo].[tempUser] (id, principal, first_name, last_name, email, isActive)
SELECT #maxId+1, A.User_Id, A.FirstName,A.LastName, 'ab#gmail.com', 1 FROM ADUser_Table A
LEFT JOIN [dbo].[tempUser] B on A.User_Id =B.principal where B.principal Is NULL
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH
END
How can I insert max id +1 with every record in sql transaction?
Instead of #maxid+1 you can add the #maxId with the row_number() as below.
SELECT #maxId+ (row_number()over(order by A.User_Id)) , A.User_Id,..
from [yourtable]
Use Row_Number while inserting as next:-
BEGIN
DECLARE #maxId INT;
SET #maxId = (SELECT MAX(id) + 1 FROM [dbo].[tempUser]);
BEGIN TRAN
BEGIN TRY
INSERT INTO [dbo].[tempUser] (id, principal, first_name, last_name, email, isActive)
SELECT row_number() over(order by A.User_Id) + #i , A.User_Id, A.FirstName,A.LastName, 'ab#gmail.com', 1 FROM ADUser_Table A
LEFT JOIN [dbo].[tempUser] B on A.User_Id =B.principal where B.principal Is NULL
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH
END
I have written the trigger below that prevents from NULL being entered in the pch_x field . It works fine if i insert 1 row but doesnt work if I enter more than one at once . Could someone please help me out a little ? Here is my code
create trigger test
ON [dbo].TEMP
for INSERT
AS
BEGIN
declare #xcheck varchar(50)
set #xcheck= (select i.pch_x FROM temp L INNER JOIN INSERTED I
ON L.id = I.id)
F (#xcheck is NULL )
begin
RAISERROR('NULL in pch_x', 16, 1)
ROLLBACK
end
END
I'm not sure why you're doing this in a trigger, but the set based way to do this test would be to use EXISTS:
create trigger test
ON [dbo].TEMP
for INSERT
AS
BEGIN
IF EXISTS(select * FROM temp L INNER JOIN
INSERTED I
ON L.id = I.id
where i.pch_x IS NULL)
begin
RAISERROR('NULL in pch_x', 16, 1)
ROLLBACK
end
END
I'm also not sure why you're joining back to the table - I'd have thought the check could run without reference to temp:
create trigger test
ON [dbo].TEMP
for INSERT
AS
BEGIN
IF EXISTS(select * FROM INSERTED
where pch_x IS NULL)
begin
RAISERROR('NULL in pch_x', 16, 1)
ROLLBACK
end
END
For you unusual requirement that, in a rowset containing some rows with nulls, you want success for those rows without nulls and failure for those rows with nulls, most sensible would be an INSTEAD OF trigger:
create trigger test
ON [dbo].TEMP
INSTEAD OF INSERT
AS
BEGIN
declare #rc int
INSERT INTO dbo.temp (/* column list */)
SELECT /* column list */ from inserted where pch_x IS NOT NULL
set #rc = ##ROWCOUNT
IF #rc <> (select COUNT(*) from inserted)
begin
RAISERROR('NULL in pch_x', 16, 1)
--ROLLBACK
end
END
If a user changes table HelloWorlds, then I want 'action they did', time they did it, and a copy of the original row insert into HelloWorldsHistory.
I would prefer to avoid a separate triggers for insert, update, and delete actions due to the column lengths.
I've tried this:
create trigger [HelloWorlds_After_IUD] on [HelloWorlds]
FOR insert, update, delete
as
if ##rowcount = 0
return
if exists (select 1 from inserted) and not exists (select 1 from deleted)
begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'INSERT', helloWorld.id, helloWorld.text ... and more from inserted
end
else
if exists (select 1 from inserted) and exists (select 1 from deleted)
begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'UPDATE', helloWorld.id, helloWorld.text ... and more from deleted
end
else
begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'DELETE', helloWorld.id, helloWorld.text ... and more from deleted
end
end
I've never seen an insert appear, but I've seen updates. I'm going to try 3 separate triggers, though maintaining the column lists will not be fun.
try something like this:
CREATE TRIGGER YourTrigger ON YourTable
AFTER INSERT,UPDATE,DELETE
AS
DECLARE #HistoryType char(1) --"I"=insert, "U"=update, "D"=delete
SET #HistoryType=NULL
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
SET #HistoryType='U'
END
ELSE
BEGIN
--INSERT
SET #HistoryType='I'
END
--handle insert or update data
INSERT INTO YourLog
(ActionType,ActionDate,.....)
SELECT
#HistoryType,GETDATE(),.....
FROM INSERTED
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
SET #HistoryType='D'
--handle delete data, insert into both the history and the log tables
INSERT INTO YourLog
(ActionType,ActionDate,.....)
SELECT
#HistoryType,GETDATE(),.....
FROM DELETED
END
--ELSE
--BEGIN
-- both INSERTED and DELETED are empty, no rows affected
--END
You need to associate (match) the rows in the inserted and deleted columns. Something like this should work better.
create trigger [HelloWorlds_After_IUD] on [HelloWorlds]
FOR insert, update, delete
as
insert into HeloWorldsHistory
select 'INSERT', helloWorld.id, helloWorld.text ... and more
from inserted
where myKeyColumn not in (select myKeyColumn from deleted)
insert into HeloWorldsHistory
select 'DELETE', helloWorld.id, helloWorld.text ... and more
from deleted
where myKeyColumn not in (select myKeyColumn from inserted)
insert into HeloWorldsHistory
select 'UPDATE', helloWorld.id, helloWorld.text ... and more
from inserted
where myKeyColumn in (select myKeyColumn from deleted)