Update a table based on a temporary table in oracle - sql

I want to update a column of a table(national_id from Personal_info) based on a value of a temporary table(nationalid from Tmp_Tbl).
Below Two tables having a pk/fk relation with each other using cid,user_id.
Users(cid,user_name)
Personal_info(user_id,national_id)
Temporary table also have a relation to Users table using user_name which is unique.
Tmp_Tbl(user_name,nationalid)
As it is oracle , i don't want to use of update join and also not merge syntax as i have the solution already.i am looking for a simple update query to use.

In Oracle, you can do this using subqueries, but you need to be careful. You need a similar subquery in the set and the where:
UPDATE Personal p
SET national_id = (SELECT t.nationalid
FROM tmp_tbl t JOIN
users u
ON t.user_name = u.user_name
WHERE u.cid = p.user_id
)
WHERE EXISTS (SELECT 1
FROM tmp_tbl t JOIN
users u
ON t.user_name = u.user_name
WHERE u.cid = p.user_id
);
If you leave out the WHERE clause, you will erase the national_id of users that are not in the temp table.
This assumes that you just want to update values for existing users. If you want to both add new users and insert values, then the code is more complicated.

Related

SQL merge statement with Joins

I am trying to use a merge statement for upsert operation. I want to do something like below where I join the both target and source table to the Student table for a unique key that only exists in the student table. Just to keep in mind, I cannot join StudentID. There could be a duplicate in my code. I need to join the schoolID for uniqueness.
Merge into GuardianTo gto inner join StudentTo sto on gto.fkStudentId = sto.StudentID
Using (Select * from GuardianFrom gfrom inner join StudentFrom sfrom on gfrom.fkStudentId = sfrom.StudentID) from
ON gto.guardianId = from.guardianId and sto.SchoolID = from.SchoolID
When....
I need to join the target guardianTo table with studentTo table to get the unique key of SchoolID. and match this ID with From tables. I know that this could be done in a separate insert and update statement (not merge), but is there a way to do something like the above using merge statement?
If you are using MSSQL you can do a merge like the code below. You need to supply a list of column names to use from your source query and then update/insert the columns you need in your target table (GuardianTo).
Merge into GuardianTo gto
Using (Select * from GuardianFrom gfrom inner join StudentFrom sfrom on gfrom.fkStudentId = sfrom.StudentID ) AS source (<column names in GuardianFrom, Studentfrom go here> )
ON (gto.guardianId = source.guardianId and gto.SchoolID = source.SchoolID)
WHEN MATCHED THEN
UPDATE SET <column in GuardianTo>= source.<column from source above> /* add any additional columns to update here*/
WHEN NOT MATCHED THEN
INSERT (guardianId, SchoolID, StudentID /* add any additional columns to insert here*/)
VALUES (source.guardianId, source.SchoolID, source.StudentID /* add any additional columns from the source to insert here*/);

How to create a table with multiple columns

Struggling with a create table statement which is based on this select into statement below:
#MaxAPDRefundAmount money = 13.00
...
select pkd.*, pd.ProviderReference, per.FirstName, per.Surname, #MaxAPDRefundAmount [MaxAPDRefundAmount],commission.Type [Commission] into #StagedData from CTE_PackageData pkd
inner join J2H.dbo.Package pk on pkd.Reference = pk.Reference
inner join J2H.dbo.Product pd on pk.PackageId = pd.PackageId
inner join J2H.dbo.FlightReservation fr on pd.ProductId = fr.ProductId
and fr.FlightBoundID = 1
inner join J2H.dbo.ProductPerson pp on pd.ProductId = pp.ProductID
and pp.StatusId < 7
inner join J2H.dbo.Flight f on fr.FlightId = f.FlightID
inner join J2H.dbo.Person per on pk.PackageId = per.PackageId
and per.PersonId = pp.PersonId
inner join J2H.dbo.PersonType pt on per.PersonTypeId = pt.PersonTypeID
We are changing a select into to just normal insert and select, so need a create table (we are going to create a temp (hash tag table) and not declaring a variable table. Also there is a pkd.* at the start as well so I am confused in knowing which fields to include in the create table. Do I include all the fields in the select statement into the create statement?
Update:
So virtually I know I need to include the data types below but I can just do:
create table #StagedData
(
pkd.*,
pd.ProviderReference,
per.FirstName,
per.Surname,
#MaxAPDRefundAmount [MaxAPDRefundAmount],
commission
)
"Do I include all the fields in the select statement into the create statement?" Well, that depends, if you need them, than yes, if not than no. It's impossible for us to say whether you need them... If you're running this exact query as insert, than yes.
As for the create statement, you can run the query you have, but replace into #StagedData with something like into TEMP_StagedData. In management studio you can let sql server build the create query for you: right-click the newly created TEMP_StagedData table in the object explorer (remember to refresh), script Table as, CREATE To and select New Query Editor Window.
The documentation of the CREATE TABLE statement is pretty straightforward.
No. Clearly, you cannot use pkd.* in a create table statement.
What you can do is run your old SELECT INTO statement as a straight SELECT (remove the INTO #stagedata) part, and look at the columns that get returned by the SELECT.
Then write a CREATE TABLE statement that includes those columns.
To create a table from a SELECT without inserting data, add a WHERE clause that never returns True.
Like this:
SELECT * INTO #TempTable FROM Table WHERE 1=0
Once the table with the columns for your SELECT, you can add additional columns with ALTER TABLE.
ALTER TABLE #TempTable ALL ExtraColumn INT
Then do your INSERT/SELECT.

How does SQL Server Update rows with more than one value?

In an update statement for a temp table, how does SQL Server decide which value to use when there are multiple values returned, for example:
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
In this situation the problem is more than one dte_start_date is returned for each id value in the temp table. There is there's no index or unique value in the tables I'm working on so I need to know how SQL Server will choose between the different values.
It is non-deterministic. See the following example for a better understanding. Though it is not exactly the same scenario explained here, it is pretty similar
When the single value is to be retrieved from the database also use the SET statement with a query to set the value. For example:
SET #v_user_user_id = (SELECT u.user_id FROM users u WHERE u.login = #v_login);
Reason: Unlike Oracle, SQL Server does not raise an error if more than one row is returned from a SELECT query that is used to populate variables. The above query will throw an exception whereas the following will not throw an exception and the variable will contain a random value from the queried table(s).
SELECT #v_user_user_id = u.user_id FROM users u WHERE u.login = #v_login;
It is non-deterministic which value is used if you have a one two many relationship.
In MS-SQL-Sever (>=2005) i would use a CTE since it's a readable way to specify what i want using ROW_NUMBER. Another advantage of a CTE is that you can change it easily to do a select instead of an update(or delete) to see what will happen.
Assuming that you want the latest record(acc.to dte_start_date) for every id:
WITH CTE AS
(
SELECT a.*, rn = ROW_NUMBER() OVER (PARTITION BY a.id
ORDER BY a.dte_start_date DESC)
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
)
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A INNER JOIN CTE ON A.ID = CTE.ID
WHERE CTE.RN = 1

Complicated sql query, take column data and insert it into another table based on criteria

I've a task at hand, which is clearly beyond my mysql skills :) I'm learning though...
I've two tables.
1. import
2. users
import contains allot of columns, such as id, user_id, user_email ...
users contains user_id and user_email
I need to migrate users content to import. Specifically I'm missing user_id in import. But it contains user_email.
So I need to think of a statement, where I match user_email from two tables and update import table with user_id from a match.
So far I've this:
SELECT u.user_id, u.user_email, i.user_email FROM users u, import i WHERE i.user_email = u.user_email;
basically you can directly update table import by joining it with user.
This is in MySQL.
UPDATE `import` a
INNER JOIN users b
ON a.user_email = b.user_email
SET a.user_id = b.user_id
For SQL Server
UPDATE a
SET a.user_id = b.user_id
FROM [import] a
INNER JOIN users b
ON a.user_email = b.user_email
If you want to match users depending on their address make sure they are unique, then you can join them like this:
UPDATE import
SET import.user_id = users.user_id
FROM import
INNER JOIN users ON import.user_email = users.user_email
You're on the right track; that would work; you may want to select other fields as needed. You can also use a JOIN statement; and then you can decide what to do with the user table; are you inserting ? updating ?
I think standard SQL supports INSERT INTO SELECT, not sure about update, but your DBMS may have a SQL extensions supporting it ...

Dynamic sql join in sql server

I have a relationship between two tables. The two tables PKs are int types.
In one table (UserS), I need to supply the Username and get the corresponding ID (which is the PK). This is the standard ASP.NET user table when using forms authentication.
However, in a related table, I want to supply the ID I find from the Users table to get a value out.
Something like:
Run query to get ID for a username (simple select/where query)
Return the result
Run a subquery where I can pass in the above result -
Get value where ID = result
This sounds a lot like dynamic sql. However, there might be a better suited and appropriate way of writing this query (on Sql Server 2k5).
How can I go about doing this and what gotchas lurk?
EDIT: I will try something along the lines of http://www.sqlteam.com/article/introduction-to-dynamic-sql-part-1
EDIT: Thanks for the tips everyone, I wrote this:
SELECT Discount.DiscountAmount
FROM Discount
INNER JOIN aspnet_Users
ON Discount.DiscountCode = aspnet_Users.UserId And aspnet_Users.Username = 's'
Where 's' is to be replaced by a parameter.
Thanks
You don't have to use dynamic SQL for that.
You can use a lookup instead:
DECLARE #ID bigint
SELECT #ID = ID FROM Users WHERE Username = #Username
SELECT
*
FROM
TableB
WHERE
ID = #ID
Then, you could add the PARAMETER #Username to your SqlCommand object, preventing the risks of SQL Injection.
Also, doing the lookup is preferable to a join, since the index is scanned a single time, for TableB.
Right, i just would do this:
SELECT *
FROM TableB
JOIN Users ON Users.Id = TableB.ID
WHERE Users.Username = #Username
Regarding lookup vs joins - while it may seem more intuitive for the novice to use the lookup, you should go with a join. A lookup needs to be evaluated for every row in your primary result set, while a join is evaluated once. Joins are much more efficient, which means that they are faster.
This is just a simple join isn't it?
SELECT x.*
FROM user_table u
INNER JOIN
other_table x
ON u.id = x.user_id
WHERE u.name = #user_name
SELECT values.value
FROM form_users, values
WHERE form_users.username = 'John Doe'
AND values.user = form_users.userid
SELECT
*
FROM
table2 t2
JOIN
UserS t1 ON t2.IDKey = t1.IDKey
WHERE
UserS.Username = #Input