update each row (sql server) based on subquery - sql

I want to update each row of table1->keyField based on table2 value
Table1
Id|keyField
1|test_500
2|test_501
3|test_501
500,501 are primary key of and my another table2
Table2
Id|value
500|A
501|B
502|C
I have tried something like
update table1 set keyField=(select value from table2 where id=substring(expression))
but my select return multiple statement so unable to run the query.
any help or direction please?

You can use the syntax like this
UPDATE table1 SET keyField = Table2.Value
FROM table1 INNER JOIN table2
ON table1.Id = substring(expression))

If I get it right, this might be what you need:
UPDATE T1 SET
keyField = T2.Value
FROM
Table1 AS T1
INNER JOIN Table2 AS T2 ON T2.id = SUBSTRING(T1.keyField, 6, 100)
Careful when comparing substring result with an numeric value, might get a conversion error.

Try this code (necessary notes are in comments below):
--generate some sample data (the same as you provided)
declare #table1 table (id int, keyField varchar(10))
insert into #table1 values (1,'test_500'),(2,'test_501'),(3,'test_502')
declare #table2 table (id int, value char(1))
insert into #table2 values (500,'A'),(501,'B'),(502,'C')
--in case you want to see tables first
--select * from #table1
--select * from #table2
--here you extract the number in first table in keyField column and match it with ID from second table, upon that, you update first table
update #table1 set keyField = value from #table2 [t2]
where cast(right(keyfield, len(keyfield) - charindex('_',keyfield)) as int) = [t2].id
select * from #table1

Related

Update statement with Where Not Exists

I am trying to do the following:
Set the status column to 1 when the row in the first table (variable) does not exist in the second one.
I tried this:
update #table1
set status=1
where NOT EXISTS (select top 1 1 from #table2 where #table1.foo=#table2.foo)
But this doesn't even compile, not recognizing #table1 in the Where statement.
Must declare the scalar variable "#table1".
Any clue about this?
Your approach is fine. You just need table aliases because the # is used to in SQL Server to represent variables (scalars or tables) and is hence problematic for aliases:
update t1
set status = 1
from #table1 t1
where not exists (select 1 from #table2 t2 where t2.foo = t1.foo);
Note that the top 1 is unnecessary in the subquery.
You can do this kind of thing by joining the two tables with a LEFT JOIN and checking the right side for NULL:
UPDATE t1
SET t1.status=1
FROM #table1 t1
LEFT JOIN #table2 t2
ON t1.foo = t2.foo
WHERE t2.foo IS NULL
The specific error you got is because you haven't got a statement declaring #table1 as a table variable, like DECLARE #table1 TABLE (foo int) for example. If table1 is not a variable, you don't need the #.
no need any top inside scaler query
update #table1
set status=1
where NOT EXISTS (select 1 from #table2 where #table1.foo=#table2.foo)
cause exists return boolean
you could use below query
update #table1
set status=1
where #table1.foo not in ( select foo from #table2 where foo is not null)
There are multiple ways - inner query with NOT IN and NOT EXISTS and JOIN query:
update tab1 set status = 1 where name not in (select name from tab2);
update tab1 set status = 1 where not exists (select 1 from tab2 where tab1.name=tab2.name);
update tab1 set status = 1 from tab1 left outer join tab2 on tab1.name = tab2.name where tab2.name is null;
Sample schema to run above queries;
create table tab1(name varchar(30), status int);
create table tab2(name varchar(30));
insert into tab1 values('a', 5);
insert into tab1 values('b', 6);
insert into tab1 values('c', 7);
insert into tab1 values('d', 8);
insert into tab2 values('a');
insert into tab2 values('d');
You have to declare table1 and table2 variables
DECLARE #table1 YOUR_TABLE1_NAME;
DECLARE #table2 YOUR_TABLE2_NAME;
update #table1
set status=1
where NOT EXISTS (select top 1 from #table2 where #table1.foo=#table2.foo)
You should use alias name for both table.
DECLARE #TABLE_1 TABLE (DEPT_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_1(DEPT_NAME,DEP_ID)
SELECT 'IT',1 UNION ALL
SELECT 'HR',2 UNION ALL
SELECT 'ACCOUNT',3 UNION ALL
SELECT 'ADMIN',4 UNION ALL
SELECT 'SALES',5 UNION ALL
SELECT 'CEO',7
DECLARE #TABLE_2 TABLE (E_ID INT,EMP_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_2(E_ID,EMP_NAME,DEP_ID)
SELECT 1,'JHON',1 UNION ALL
SELECT 2,'LITA',2 UNION ALL
SELECT 3,'MATT',1 UNION ALL
SELECT 4,'JEFF',1 UNION ALL
SELECT 5,'BROCK',2 UNION ALL
SELECT 6,'BOB',5 UNION ALL
SELECT 7,'SAM',4 UNION ALL
SELECT 8,'DAVID',3 UNION ALL
SELECT 9,'JACK',1 UNION ALL
SELECT 10,'GARY',4 UNION ALL
SELECT 11,'DONALD',6
SELECT * FROM #TABLE_1 A WHERE NOT EXISTS (SELECT DEP_ID FROM #TABLE_2 B WHERE A.DEP_ID=B.DEP_ID )

Replace empty values as 0 instead of null while joining two tables in sql

I have join two tables t1 and t2. The output produces some null records since there is no data in the table t2. Instead of showing null I want to show 0 since I have to perform some arithmetic operation in the crystal reports.
please help me.....
sample example
declare #t table (ID int)
declare #t1 table (ID int)
insert into #t (id) values (1)
select t.ID,ISNULL(TT.ID,0)id from #t t
LEFT JOIN #t1 tt
ON t.ID = tt.ID
Use the COALESCE function which automatically replace null values as 0.
Sample
SELECT COALESCE(total_amount, 0) from #Temp1

Use default value of a column in stored procedures

I am using SQL Server 2012 and I have 2 tables with the following definition
CREATE TABLE t1 (id INT PRIMARY KEY, value NVARCHAR(10))
CREATE TABLE t2 (id INT PRIMARY KEY, value BIT DEFAULT 1)
ALTER TABLE t2 WITH CHECK ADD CONSTRAINT FK FOREIGN KEY(id) REFERENCES t1 (id)
I inserted the following columns for the current example:
INSERT INTO t1 VALUES (1, 'a')
INSERT INTO t1 VALUES (2, 'b')
INSERT INTO t1 VALUES (3, 'c')
INSERT INTO t2 VALUES (1, 1)
INSERT INTO t2 VALUES (3, 0)
I am running this query and it works
SELECT
t1.*, ISNULL(t2.value, 1)
FROM
t1
LEFT JOIN t2 ON t1.id = t2.id
Is there any way to replace the 1 in this part ISNULL(t2.value, 1) with the default value that I have defined in the column value in the table t2?
Here is the sqlfiddle I created with this example: SQLFIDDLE DEMO
UPDATE 1:
I can't use SQL Server: Find out default value of a column with a query because it returns ((1)) and I can't cast ((1)) to BIT.
Is there any way to fix that?
You are not using the default in the manner it is intended. It is something SQL Server evaluates internally at time of insert (or potentially update if the default keyword is used).
It is not intended for use in SELECT. Consider that it can contain arbitrary expressions such as DEFAULT CAST(GETDATE() AS INT) % 2 or calling a Scalar UDF. Casting from string to bit won't evaluate those expressions for you.
The only way you could do something like this would be to evaluate it separately
DECLARE #B BIT
, #Definition NVARCHAR(max)
SELECT #Definition = N'SELECT #B = '
+ object_definition(default_object_id)
FROM sys.columns
WHERE NAME = 'value'
AND object_id = OBJECT_ID('dbo.t2')
EXEC sys.sp_executesql
#Definition,
N'#B BIT OUTPUT',
#B = #B OUTPUT
SELECT t1.*,
ISNULL(t2.value, #B)
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
This works for me:
DECLARE #def as bit = null
SELECT #def
UNION ALL
SELECT ISNULL(#def, REPLACE(REPLACE((
SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'dual'
AND COLUMN_NAME = 'tempo'),'(', ''), ')', '')) As def

please help me to create multi insert query

I have got two table
create table t1(cid int, isnews int)
create table t2(nid int,cid int, isnews int)
situations is like this:
if t2 contain t2.cid = t1.cid then the t2.isnews = t1.news and
if t2 not contain cid of t1 then new record should be inserted in t2 and that t1.cid, t1.isnews should be inserted in t2..
and complete table should be done in single query... i have done the updation part but not able to do insertion part..
update query:
UPDATE t22
SET t22.isnews = t11.isnews
FROM t2 AS t22
JOIN t1 AS t11
ON t11.cid= t22.cid
i have prepared below cursor for insert... is it good? :
DECLARE #clntid INT
DECLARE #clntnewsltr INT
DECLARE clientnews CURSOR FOR
SELECT clientid,newsLetter
FROM clients
WHERE clientid NOT IN (SELECT clientid FROM clientprivacy)
OPEN clientnews
FETCH NEXT FROM clientnews INTO #clntid,#clntnewsltr
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO clientprivacy (clientId,tdNewsLetters) VALUES(#clntid, #clntnewsltr)
FETCH NEXT FROM clientnews INTO #clntid,#clntnewsltr
END
CLOSE clientnews
DEALLOCATE clientnews
I think this is the kind of thing you're after:
--INSERT t2 (cid, isnews)
SELECT t1.cid, t1.isnews
FROM t1
LEFT JOIN t2 ON t1.cid = t2.cid
WHERE t2.cid IS NULL
I've commented out the INSERT line - I recommend you run the SELECT on it's own first to check it does give you the correct result (all records from t1 that don't have a matching cid in t2).
I've assumed t2.nid is an IDENTITY column.
You will be so much better off without cursors :) Cursors take MUCH longer to run in large data sets.
It is true you can use a LEFT JOIN, but you can also use a SELECT in your WHERE clause. Most of the time it's a style choice.
CREATE TABLE table1(col_1 int, col_2 int)
CREATE TABLE table2(nid int, col_1 int, col_2 int)
INSERT INTO table2 (col_1,col_2)
SELECT col_1,col_2
FROM table1
WHERE col_1 NOT IN (SELECT col_1 FROM table2)

If Record Exists, Update Else Insert

I'm trying to move some data between two SQL Server 2008 tables. If the record exists in Table2 with the email from Table1 then update that record with the data from Table1, else insert a new record.
In Table1 I have a number of columns; first name, surname, email and so on.
I'm not quite sure how to structure the query to update Table2 if the email from Table1 exists or insert a new row if email from Table1 does not exist in Table2.
I tried doing a few searches on Google but most solutions seem to work by creating some stored procedure. So I wondered if anyone might know how to build a suitable query that might do the trick?
I think MERGE is what you want.
MERGE
INTO table2 t2
USING table1 t1
ON t2.email = t1.email
WHEN MATCHED THEN
UPDATE
SET t2.col1 = t1.col1,
t2.col2 = t1.col2
WHEN NOT MATCHED THEN
INSERT (col1, col2)
VALUES (t1.col1, t1.col2)
Microsoft released a tool to compare data between SQL tables, this might a good option in certain situations.
Edit: Forgot to mention, it also generates a script to insert/update missing or different rows.
For completeness, I hacked up this query which does what you want, it updates existing table2 records, and adds those that are missing, based off the email address.
The 'updating' and 'insert missing' queries below are the ones you want.
BEGIN TRAN
create table #table1 (id int, fname varchar(20), email varchar(20))
insert into #table1 values (1, 'name_1_updated', 'email_1')
insert into #table1 values (3, 'name_3_updated', 'email_3')
insert into #table1 values (100, 'name_100', 'email_100')
create table #table2 (id int, fname varchar(20), email varchar(20))
insert into #table2 values (1, 'name_1', 'email_1')
insert into #table2 values (2, 'name_2', 'email_2')
insert into #table2 values (3, 'name_3', 'email_3')
insert into #table2 values (4, 'name_4', 'email_4')
print 'before update'
select * from #table2
print 'updating'
update #table2
set #table2.fname = t1.fname
from #table1 t1
where t1.email = #table2.email
print 'insert missing'
insert into #table2
select * from #table1
where #table1.email not in (select email from #table2 where email = #table1.email)
print 'after update'
select * from #table2
drop table #table1
drop table #table2
ROLLBACK