How to update “row number” column values 1..N after rows are DELETED? - sql

I have this table:
When I make a delete of a box in this table, I need to make an increment of all the following rows.
For example: if I delete BoxNo '4' then the rows which are after the last row of BoxNo '4' (5,6,7,..etc) have to make an increment by 1 and be like (4,5,6,...etc.). I hope I succeed in explaining the problem.
Could you please kindly help me to perform this with an SQL Server query?
Thanks in advance.

Executing actions automatically after rows are deleted is what TRIGGERS are for.
In your case, it looks something like:
CREATE TRIGGER MyTable_AfterDelete
ON MyTable
FOR DELETE
AS
update MyTable set RowCounter = RowCounter + 1
from deleted
inner join MyTable on MyTable.BoxNo > deleted.BoxNo
GO
As you can see SQL Server doesn't raise a trigger after each row deleted but after each DELETE statement execution, which can involve several rows deleted, so we need to use the "deleted" pseudo-table to apply our action on every one of those rows deleted.
PS: This is how what you asked can be done, although I agree with the comments that say that you could structure better this problem instead of needing to update so many rows after every delete.
UPDATE
If you want to execute it manually on every delete instruction, instead of automatically on a trigger, you can pass a parameter to your DELETE statement on C# in order to update the posterior RowCounters. Something like:
delete from MyTable where BoxNo = #BoxNo
update MyTable set RowCounter = RowCounter + 1 where BoxNo > #BoxNo

Related

Concat specific string to every inserted row

This is an hypothetical case..
I'm trying to find a good approach to make sure that every value inserted in an specific column col1 of my table mytable has a specific string http:// at the begining of the value.
Example:
I want to insert myprofile into mytable so (after my check condition..) the final value would be http://myprofile
I guess that a good approach could be using a trigger on insert but I didn't find anything concrete yet..
Any ideas?
Thank you.
You can try something like this as a starting point - this is for SQL Server (don't know MySQL well enough to provide that trigger code for you):
-- create the trigger, give it a meaningful name
CREATE TRIGGER PrependHttpPrefix
ON dbo.YourTableName -- it's on a specific table
AFTER INSERT, UPDATE -- it's for a specific operation, or several
AS
BEGIN
-- the newly inserted rows are stored in the "Inserted" pseudo table.
-- It has the exact same structure as your table that this trigger is
-- attached to.
-- SQL Server works in such a way that if the INSERT affected multiple
-- rows, the trigger is called *once* and "Inserted" contains those
-- multiple rows - you need to work with "Inserted" as a multi-row data set
--
-- You need to join the "Inserted" rows to your table (based on the
-- primary key for the table); for those rows newly inserted that
-- **do not** start with "http://" in "YourColumn", you need to set
-- that column value to the fixed text "http:/" plus whatever has been inserted
UPDATE tbl
SET YourColumn = 'http://' + i.YourColumn
FROM dbo.YourTableName tbl
INNER JOIN Inserted i ON tbl.PKColumn = i.PKColumn
WHERE LEFT(i.YourColumn, 7) <> 'http://'
END

SQL Server insert trigger not working

This is my first time using triggers.
My trigger is not being triggered please help.
CREATE TRIGGER sbhack_autoban
ON LOG_CONNECT201211
FOR INSERT
AS
BEGIN
/* query to run if single or multiple data is
inserted into LOG_CONNECT201211 table */
UPDATE login.dbo.USER_CHECK_LOGIN
SET login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 2
WHERE login.dbo.USER_CHECK_LOGIN.USER_KEY IN
(SELECT e.USER_KEY
FROM game.dbo.CHAR_DATA0 AS e
INNER JOIN gamelogs.dbo.LOG_USING_DEPOT201211 AS p
ON e.CHAR_KEY = p.CHAR_KEY
WHERE p.GATENUM = 150)
AND login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 0
AND login.dbo.USER_CHECK_LOGIN.USER_KEY != 51;
END
This is suppose to run the query inside the BEGIN : END if an entry is inserted into the LOG_CONNECT201211 table. But nothing is happening even when I have inserted multiple data into LOG_CONNECT201211.
When your INSERT trigger fires - then at least one new row has been inserted! That's a fact.
Now the question is: given that a single or multiple new rows have been inserted - what do you want to do with this knowledge??
Typically, you could e.g. set a column to a value you cannot specify as a default constraint - or you could insert the fact that the row has been inserted into an audit table or something....
So you'd have something like this:
CREATE TRIGGER sbhack_autoban
ON LOG_CONNECT201211
FOR INSERT
AS
INSERT INTO LogAudit(InsertedDate, UserKey)
SELECT
GETDATE(), i.User_Key
FROM
Inserted i
or something like that....
Update: ok, so you want to run that UPDATE statement when the rows have been inserted - not 100% clear, what columns/values from the inserted rows you want to use - looks like the e.UserKey column only - correct?
Then the UPDATE would be:
UPDATE login.dbo.USER_CHECK_LOGIN
SET login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 2
WHERE
login.dbo.USER_CHECK_LOGIN.USER_KEY IN
(SELECT USER_KEY FROM Inserted)
AND login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 0
AND login.dbo.USER_CHECK_LOGIN.USER_KEY != 51;
Update #2:
The point I still don't understand is : why do you want to run an update that uses the USER_CHECK_LOGIN, CHAR_DATA0 and LOG_USING_DEPOT201211 tables, when some rows are getting inserted into a totally separate, unrelated table LOG_CONNECT201211 ??
A trigger is used when you want to do something because rows have been inserted into that table - but in that case, you typically want to do something with the rows and their values that have been inserted...
I just don't see any connection between the rows being inserted into LOG_CONNECT201211 event, and the tables you are then querying from and updating. Where's the link?? WHY do you need to run *this UPDATE when data is inserted into LOG_CONNECT201211 ?? It would make sense if data where inserted into one of the tables involved in the UPDATE - but like this, it just totally doesn't make any sense .....

Rollback the changes for Update Query

UPDATE UPI_ATTRIBUTE SET SITE_INC ='0'
WHERE USER_PROFILING_NAME IN ('CAR_IMPLICIT','CAR_EXPLICIT')
Above is my query that I am using to update the columns in UPI_ATTRIBUTE table. And suppose if I need to rollback the above changes that I am doing with update query, then how can I use the delete query in the above case? Currently SITE_INC is empty. So after updating the table it will have 0 in that. And If I need to rollback the changes then I need to make it empty again.
How can I delete the value 0 from above column after updating.
You cannot "delete" data to rollback an update.
Even if the only change that you'll do is set a flag from "NULL" to "Y" and vice versa, you can't really determine which value to update when you do multiple updates.
update 1 : set from "NULL" to "0"
update 2 : set from "0" to "something else"
update 3 : Rollback changes (rollback to which state)?
If you want to really rollback changes to specific rows (instead of the complete table, which can be done using Flashback), you can audit the changes to "remember" the values and then revert back to them.
Even then, you should consider which point to revert to, when you have multiple updates.
Not sure Oracle have final table/old table function for select/update.
For DB2 for z/OS, it have such function:
SELECT LASTNAME, BONUS FROM FINAL TABLE
(UPDATE EMP SET BONUS = BONUS * 1.3
WHERE JOB = 'CLERK');
Then, the result set of the select include all the updated rows. you can use rownum or other unique value, then you can update it back to any value as you want.

How to check if a column is being updated in an INSTEAD OF UPDATE Trigger

I am making some tweaks to a legacy application built on SQL Server 2000, needless to say I only want to do the absolute minimum in the fear that it may just all fall apart.
I have a large table of users, tbUsers, with a BIT flag for IsDeleted. I want to archive off all current and future IsDeleted = 1 user records into my archive table tbDeletedUsers.
Moving the currently deleted users is straight forward, however I want a way to move any future users where the IsDeleted flag is set. I could use a standard AFTER trigger on the column however I plan to add some constraints to the tbUser table that would violate this, what I'd like is for my INSTEAD OF UPDATE trigger to fire and move the record to archive table instead?
I guess my question is... is it possible to trigger an INSTEAD OF UPDATE trigger on the update of an individual column? This is what I have so far:
CREATE TRIGGER trg_ArchiveUsers
INSTEAD OF UPDATE ON tbUsers
AS
BEGIN
...
END
GO
If so an example (SQL 2000 compatible) would be much appreciated!
Using the UPDATE(columnname) test, you can check in a trigger whether a specific column was updated (and then take specific actions), but you can't have a trigger fire only on the update of a specific column. It will fire as soon as the update is performed, regardless of the fact which column was the target of the update.
So, if you think you have to use an INSTEAD OF UPDATE trigger, you'll need to implement two kinds of actions in it:
1) insert into tbDeletedUsers + delete from tbUsers – when IsDeleted is updated (or, more exactly, updated and set to 1);
2) update tbUsers normally – when IsDeleted is not updated (or updated but not set to 1).
Because more than one row can be updated with a single UPDATE instruction, you might also need to take into account that some rows might have IsDeleted set to 1 and others not.
I'm not a big fan of INSTEAD OF triggers, but if I really had to use one for a task like yours, I might omit the UPDATE() test and implement the trigger like this:
CREATE TRIGGER trg_ArchiveUsers
ON tbUsers
INSTEAD OF UPDATE
AS
BEGIN
UPDATE tbUsers
SET
column = INSERTED.column,
…
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 0
;
DELETE FROM tbUsers
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 1
;
INSERT INTO tbDeletedUsers (columns)
SELECT columns
FROM INSERTED
WHERE IsDeleted = 1
;
END

Need some help with Sql Server and a simple Trigger

I wish to make a trigger but i'm not sure how to grab the data for whatever caused the trigger.
I have a simlpe table.
FooId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
I wish to have a trigger so that when an UPDATE, INSERT or DELETE occurs, i then do the following.
Pseduocode
IF INSERT
Print 'Insert' & Name
ELSE IF UPDATE
Print 'Update' & FooId & Name
ELSE IF DELETE
Print 'Delete' & FooId & Name
Now, I know how to make a trigger for a table.
What i don't know how to do is figure out the values based on what the trigger type is.
Can anyone help?
Edit: Not sure if it helps, but db is Sql Server 2008
the pseudo table "inserted" contains the new data, and "deleted" table contains the old data.
You can do something like
create trigger mytrigger on mytable for insert, update, delete
as
if ( select count(*) from inserted ) > 0
-- insert or update
select FooId, Name from inserted
else
-- delete
select FooId, Name from deleted
To clarify all the comments made by others, on an insert, the inserted table contains data and deleted is empty. On a delete, the situation is reversed. On an update, deleted and inserted contain the "before" and "after" copy of any updated rows.
When you are writing a trigger, you have to account for the fact that your trigger may be called by a statement that effects more than one row at a time.
As others have pointed out, you reference the inserted table to get the values of new values of updated or inserted rows, and you reference the deleted table to get the value of deleted rows.
SQL triggers provide an implicitly-defined table called "inserted" which returns the affected rows, allowing you to do things like
UPDATE mytable SET mytimestamp = GETDATE() WHERE id IN (SELECT id FROM inserted)
Regarding your code sample, you'll want to create separate INSERT, UPDATE and DELETE triggers if you are performing separate actions for each.
(At least, this is the case in SQL Server... you didn't specify a platform.)
On 2008, there is also MERGE command. How do you want to handle it?
Starting from 2008, there are four commands you can modify a table with:
INSERT, UPDATE, DELETE, and MERGE:
http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx
http://sqlblogcasts.com/blogs/grumpyolddba/archive/2009/03/11/reasons-to-move-to-sql-2008-merge.aspx
What do you want your trigger to do when someone issues a MERGE command against your table?