T-SQL Update Statement WHERE clause with table alias - sql-server

Right I'm getting myself confused so just want to clarify, let's say I want to do the following update inside a trigger. The trigger is on a table called tblCustomers:
UPDATE tblContacts
SET tblContacts.ContactName = I.ContactName
FROM tblContacts cont
INNER JOIN inserted I ON cont.customerID = I.customerID
Will that only update the records from the inner join between inserted and tblContacts, i.e. in most cases just one record, or do I need to include a WHERE clause?
Also, am I OK to use the alias (cont) in the where clause or do I need to use tblContacts?
Sorry I know this is silly but I'm getting myself more and more confused! Thanks!

Will that only update the records from the inner join between inserted and tblContacts, i.e. in most cases just one record
Yes. That can be one or multiple rows - depending on what your statement that causes the trigger to fire actually did - but it will only ever update those rows that are part of the Inserted table
Also, am I OK to use the alias (cont) in the where clause or do I need to use tblContacts?
You can definitely use the table alias! In fact, when you define a table alias, you have to use it.

Your update query will update all tblContacts.ContactName values wherever there is a match per ON clause defined ON cont.customerID = I.customerID. So if 10 rows matches then 10 values (10 rows) will be affected.
Again, yes you can use the table alias in WHERE condition.

Related

Number of rows updated in a oracle table

I have a table called t1 which is already updated by a file. I have table t2 which is created as backup for table t1 before modifications. Now I want to know how many records got updated in table t1. Is there anyway that I can do join with back up table and know how many records got altered? Or how to use sql%rowcount function on a already updated table? Or how should i proceed with ALL_TAB_MODIFICATIONS?
You can join the tables on their primary key (cos you didn't update that, hopefully!) and then compare every column.. you'll have to check for nulls too, and it'll make quite a lot of typing. You could use all_tab_cols and a bit of sql to create your query though (write an sql that creates sql as its output )
Actually, thinking about it, you might be able to get away with less typing by doing a natural join the tables together to get a set of rows that didn't change and removing that set from the original full set:
select * from original
Minus
select original.* from original natural inner join backup
Ive never done it, but the theory is that natural join joins on all equal column names so every column of each table will feature in the join condition. It's an inner join so only columns that have not changed will be represented. Any columns that have become null or become valued from null will also disappear. This is hence the set of rows that have not changed. If all you're after is a count, do a count of the original table less the count of this join result. If you want to know which rows changed, do the result set minus.
Ideally you shouldn't do this; instead at the point the update is run, capture the number of rows it affected. However, this technique could be used long after the update was performed (but before some other update was run)

sql query to find all the updated column of a table

I need a dynamic sql query that can get a column values of a table on the basis of any case/condition. I want to do that while update any record. And I need updated value of column and for that I am using Inserted and Deleted tables of SQL Server.
I made one query which is working fine with one column but I need a generic query that should work for all of the columns.
SELECT i.name
FROM inserted i
INNER JOIN deleted d ON i.id = d.id
WHERE d.name <> i.name
With the help of above query we can get "Name" column value if it's updated. But as it's specific to one column same thing I want for all the columns of a table in which there should be no need to define any column name it should be generic/dynamic query.
I am trying to achieve that by adding one more inner join with PIVOT of "INFORMATION_SCHEMA.COLUMNS" for columns but I am not sure about it whether we can do that or not by this.
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '%table1%'
You can't get that kind of information using just a query. It sounds like you need to be running an update trigger. In there you can code the criteria get your columns, etc. From your question, it sounds like only one column can be updated, you are just not sure which one it will be. If multiple columns are being updated, that complicates things, but not that much
There are several ways that you can get the data you need. Off the top, I'd suggest some simple looping once you get the column names.
What has worked for me in similar scenarios is to do a simple query to INFORMAATION_SCHEMA.Columns and put the results in a table variable. From there, iterate through the table variable to get one column name at a time and run a simple dynamic query to see if the value has changed.
Hope this helps.
:{)

Create Trigger to modify a row to the value on a joined table

I have a tables job_costcodes(id, cost_code_no, dept_id) and cost_codes(code_code_no, dept_id).
I am trying to make it so if job_costcodes.cost_code_no is modified, job_costcodes.dept_id is filled with the appropriate one from the cost_codes table, based on a matching code_code_no.
So referring to the tables below, if the top row in job_costcodes is changed to 10, the dept_id should change to 1212. Or 20 to 1313, etc.
I am not sure exactly how the syntax works... here is what I have so far.
UPDATE: updated code.. i think it works now.
create trigger update_test on dbo.job_costcodes
for update, insert
as
begin
set nocount on
update dbo.job_costcodes
set dept_id = (select CASE WHEN COUNT(1) > 0 THEN MIN(dbo.cost_codes.dept_id) ELSE NULL END as Expr1
FROM inserted INNER JOIN
dbo.cost_codes ON dbo.cost_codes.cost_code_no = inserted.cost_code_no)
from inserted as i
inner join dbo.[job_costcodes] on dbo.[job_costcodes].id = i.id
end
Treating your question as academic, start off by looking up the CREATE TRIGGER command in TSQL to get a solid understanding of the virtual tables inserted and deleted.
Then here is what I would do, in pseudo-cod-ish descriptive terms:
In your trigger, simply UPDATE job_costcodes and set the value of dept_id to the corresponding dept_id in cost_codes by JOINing to cost_codes and inserted in the FROM clause of the UPDATE.
There is no need to verify that the cost_code_no changed when doing this, the result will be the same, but if you feel you must do this, then look at the IF UPDATE() function in TSQL. You can then compare the value of cost_code_no in inserted vs deleted to know if it changed at all.

Can I use a cursor in the select part of a SQL query?

I would like to select columns from two tables and add an extra and put this into a table. My question is can I use a cursor to loop through a table and calculate a value and then assign this to the new column in the select part like below
SELECT a.cola,
a.colB,
b.colC,
b.colD,
(CURSOR TO LOOP THROUGH a table and then calculate some value) as new column
INTO NEWTABLE
FROM a
INNER JOIN b
ON a.id=b.id
WHERE etc
I just need to know that this is possible?
You can use a correlated subquery (it does mean you will have to ensure only one value per record is possible to be returned though) but it is far better to do this through joins, if possible, for performance reasons. You should never consider looping as a way to get data if a set-based alternative works.

Confused about SQL Server trigger that does an UPDATE (strange UPDATE statement format)

The crux of my question is the following style of UPDATE statement in a trigger:
update ActualTableName
set X=Y
from inserted
I would have thought that this is a syntax error... the table "ActualTableName" does not appear in the "from" clause.
So... is this just some sort of funky automatic alias "unwind" (i.e. it knows "inserted" is an alias for ActualTableName? This seems unlikely because of a later query (see below).
Or... is there something more... like the query is expanded to:
update ActualTableName
set X=Y
from ActualTableName
cross join inserted
This also gets a bit stranger with a more complicated UPDATE that references both the inserted and deleted tables:
update ActualTableName
set [... some assignments ...]
from
inserted
left outer join deleted
on inserted.Id = deleted.Id
and inserted.SomeField > deleted.SomeField
where
inserted.Id <> ActualTableName.Id and
This query appears to be updating records in ActualTableName that are not part of the inserted table... and this leads me to think that the actual query is:
update ActualTableName
set [... some assignments ...]
from
ActualTableName
cross jon inserted
left outer join deleted
on inserted.Id = deleted.Id
and inserted.SomeField > deleted.SomeField
where
inserted.Id <> ActualTableName.Id and
The books online are a bit opaque about this, and says this:
If the object being updated is the same as the object in the FROM
clause and there is only one reference to the object in the FROM
clause, an object alias may or may not be specified. If the object
being updated appears more than one time in the FROM clause, one, and
only one, reference to the object must not specify a table alias. All
other references to the object in the FROM clause must include an
object alias.
So... can anyone provide clarity as what is going on?
I'm not sure if you are aware of the fact that Inserted or Deleted in the above mentioned queries are not alias but special tables used by the SQL server to track insertion, update or deletion of data within triggers. Here is more information:
http://msdn.microsoft.com/en-us/library/ms191300.aspx

Resources