I need to convert scripts for SQL Server, so I can use them for SQLite.
The scripts look like this:
DECLARE #var1 int = (SELECT Id FROM Table1 WHERE id = 'val1')
DECLARE #var2 int = (SELECT Id FROM Table2 WHERE id = 'val2')
IF NOT EXISTS(SELECT * FROM Table3 WHERE id_1 = #var1 and id_2 = #var2)
INSERT INTO Table3(id_1, id_2) VALUES (#var1, #var2)
GO
IF NOT EXISTS(SELECT * FROM Table4 WHERE id ='val3')
INSERT INTO Table4(id, desc) values ('111', 'new entry')
GO
What is the best practice for executing these scripts in SQLite?
SQLite does not support variables.
You can use a CTE that returns the values of the 2 variables as columns:
WITH cte(var1, var2) AS (
SELECT (SELECT Id FROM Table1 WHERE id = 'val1'), (SELECT Id FROM Table2 WHERE id = 'val2')
)
INSERT INTO Table3(id_1, id_2)
SELECT var1, var2
FROM cte
WHERE NOT EXISTS (SELECT * FROM Table3 t3 INNER JOIN cte c ON t3.id_1 = c.var1 AND t3.id_2 = c.var2);
INSERT INTO Table4(id, `desc`)
SELECT '111', 'new entry'
WHERE NOT EXISTS (SELECT * FROM Table4 WHERE id ='val3')
Related
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 )
I need to do something like this:
SET #MyTableAsArgument = 'Foo;Bar\n1;2\n3;4\n'; -- CSV or any other table-format
SET #AnOtherArgument = 'somedata';
SELECT * FROM table1 t1, #MyTableAsArgument t2
WHERE t1.foo = t2.foo
AND t1.bar = #AnOtherArgument
Is there a way to do this?
The only other solution I see is:
Create a temporary table tmp1
Insert my MyTableAsArgument to the tmp1
Do My query on table1 and tmp1
Delete my temporary table tmp1
I am not sure if this is an abuse of temporary tables.
Is there a significant performance overhead with temporary tables as they are used for queries?
Can you use a table variable or temporary table?
DECLARE #MyTable TABLE (foo VARCHAR(255));
INSERT INTO #MyTable (foo)
VALUES ('Foo'), ('Bar\n12\n3'), ('4\n');
SET #AnOtherArgument = 'somedata';
SELECT t1.*
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM #MyTable) AND
t1.bar = #AnOtherArgument;
If this is not possible, you can use a SPLIT() functions -- STRING_SPLIT() is built into the most recent versions -- but other versions are on the web:
SELECT *
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM string_split(#MyTableLIST, ';') ss(foo)) AND
t1.bar = #AnOtherArgument;
#Cosinus, there is a temp table variable too in SQL. This allows you to define the columns you want in that table and using a 'union all' you can insert elements in that table.
See this mockup below.
DECLARE #MyTableAsArgument table(Name varchar(20), foo varchar(50), descb varchar(100), pj_id int)
DECLARE #AnOtherArgument varchar(20) = 'somedata';
INSERT into #MyTableAsArgument
SELECT 'James', 'iphone', 'cell phone', 1 union all
SELECT 'Michael', 'macbook', 'laptop', 2 union all
SELECT 'Henry', 'windows', 'os', 3
SELECT *
FROM
table1 t1
Join #MyTableAsArgument t2 ON
t1.foo = t2.foo
AND
t1.bar = #AnOtherArgument
From doing a bit of research it seems it’s not possible to do an insert with a where clause?
I have a table I want to import into another table where specific record criteria doesn’t already exist. How would I go about this ?
E.g pseudo code -
insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tableb.column2 = tablea.column2
Could this potentially be done with a Join ?
You can insert using INSERT INTO.. SELECT with NOT EXISTS.
Query
insert into [TableB]
select * from [TableA] as [t1] -- [TableA] and [TableB] structure should be same.
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
Or, if the table structure is not same and need to same few columns, then
Query
insert into [TableB]([column1], [column2], ..., [columnN])
select [column1], [column2], ..., [columnN]
from [TableA] as [t1]
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
You can also use LEFT JOIN with IS NULL as below:
INSERT INTO tableb
SELECT a.*
FROM tablea a
LEFT JOIN tableb b ON b.column1 = a.column1
AND b.column2 = a.column2
WHERE b.column1 IS NULL
Referencing table name from INSERT statement in SELECT part will not work, because INSERT is not a query itself, but nothing prevents to query destination table in SELECT, which produces the data set to be inserted.
INSERT INTO tableb (column1, column2)
SELECT column1, column2 FROM tablea
WHERE NOT EXISTS (SELECT * FROM tableb
WHERE tableb.column1 = tablea.column1
AND tabled.column2 = tablea.column2)
Try this :
Via Insert with Select statement with Not Exists
Declare #table1 table(Id int , EmpName varchar(100) )
Declare #table2 table(Id int , EmpName varchar(100) )
Insert into #table1 values (1,'Ajay'), (2, 'Tarak') , (3,'Nirav')
Insert into #table2 values (1,'Ajay')
--Insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tabled.column2 = tablea.column2
INSERT INTO #table2 (id, empname)
select id, empname from #table1
EXCEPT
SELECT id, empname from #table2
Select * from #table1
Select * from #table2
Via merge
Insert into #table2 values (4,'Prakash')
Select * from #table1
Select * from #table2
Declare #Id int , #EmpName varchar(100)
;with data as (select #id as id, #empname as empname from #table1)
merge #table2 t
using data s
on s.id = t.id
and s.empname = t.empname
when not matched by target
then insert (id, empname) values (s.id, s.empname);
Select * from #table1
Select * from #table2
I want to delete from t2 if same value of itemid,storeid,MSRTime does not exist on t1 and Same value of itemid,storeid,MSRTime exist on t3 and status is D. In below example i should be able to delete second row on t2 but not 1st row.
Table 1: t1
itemid |storeid|MSRTime
x y z
Table 2: t2
itemid |storeid|MSRTime
x y z
a b c
Table 3: t3
itemid |storeid|MSRTime|status
x y z D
a b c D
I tried doing this using join but i could not reach the desired result. Please help.
Thank You.
You can write the query almost exactly as you've described it:
declare #t1 table(itemid varchar(7),storeid varchar(9),MSRTime varchar(3))
insert into #t1(itemid,storeid,MSRTime) values
('x','y','z')
declare #t2 table(itemid varchar(7),storeid varchar(9),MSRTime varchar(3))
insert into #t2(itemid,storeid,MSRTime) values
('x','y','z'),
('a','b','c')
declare #t3 table(itemid varchar(7),storeid varchar(9),MSRTime varchar(3),status varchar(4))
insert into #t3(itemid,storeid,MSRTime,status) values
('x','y','z','D'),
('a','b','c','D')
delete from t2
from #t2 t2
inner join
#t3 t3
on
t2.itemid = t3.itemid and
t2.storeid = t3.storeid and
t2.MSRTime = t3.MSRTime and
t3.status = 'D'
where
not exists (
select *
from #t1 t1
where t1.itemid = t2.itemid and
t1.storeid = t2.storeid and
t1.MSRTime = t2.MSRTime
)
select * from #t2
Result:
itemid storeid MSRTime
------- --------- -------
x y z
Should be something like this
-- delete t2
select *
from table2 t2
JOIN table3 t3 on t2.itemid = t3.itemid and
t2.storeid = t3.storeid and
t2.MSRTime = t3.MSRTime
LEFT JOIN table1 t1 on t2.itemid = t1.itemid and
t2.storeid = t1.storeid and
t2.MSRTime = t1.MSRTime
where t1.itemID IS NULL
Run the select first, if it gives you back right row, just un-comment delete and you are good to go
I have created the whole script for your reference. Please use the last DELETE query for your scenario. That will do the trick.
CREATE TABLE #T1
(itemid VARCHAR(10)
,storeid VARCHAR(10)
,MSRTime VARCHAR(10))
INSERT INTO #T1 VALUES ('x','y','z')
SELECT * FROM #T1
GO
CREATE TABLE #T2
(itemid VARCHAR(10)
,storeid VARCHAR(10)
,MSRTime VARCHAR(10))
INSERT INTO #T2 VALUES ('x','y','z'),('a','b','c')
SELECT * FROM #T2
GO
CREATE TABLE #T3
(itemid VARCHAR(10)
,storeid VARCHAR(10)
,MSRTime VARCHAR(10)
,status VARCHAR(10))
INSERT INTO #T3 VALUES ('x','y','z','D'),('a','b','c','D')
SELECT * FROM #T3
GO
DELETE M
FROM #T2 AS M INNER JOIN
(SELECT itemid,storeid,MSRTime FROM
(SELECT itemid,storeid,MSRTime FROM #T3 WHERE status='D') T1
INTERSECT
(SELECT itemid,storeid,MSRTime FROM
(SELECT * FROM #T2
EXCEPT
SELECT * FROM #T1) T2)) X
ON X.itemid = M.itemid AND X.storeid = M.storeid AND X.MSRTime = M.MSRTime
GO
Not sure if this matches your environment, but programmatically it may be beneficial to limit the results you are comparing with the joins to only those that have a value of D in status. I would also try making a compound key using Coalese so that you are not having to match on three separate joins.
For example -
itemid |storeid|MSRTime|Key
x y z xyz
a b c abc
I have the following temp table structure:
CREATE TABLE #TempTable (
ID INT,
CId TINYINT,
TagId INT,
Beginning_X DECIMAL(18,5),
Beginning_Y DECIMAL(18,5),
Ending_X DECIMAL(18,5),
Ending_Y DECIMAL(18,5))
INSERT INTO #TempTable (ID, CId, TagId, Beginning_X, Beginning_Y)
SELECT ID, CId,TagId, X, Y
FROM Table_1
WHERE IsRepeat = 1
INSERT INTO #TempTable(Ending_X, Ending_Y)
SELECT X,Y
FROM Table_1 t
WHERE t.ID IN (SELECT ID+1
FROM Table_1
where IsRepeat = 1))
The second insert removes all the values from the first insert statement and I can't figure out why. I want to append the the results from the second insert to the first insert and have one solid table.
EDIT: I think I found the solution:
UPDATE t
SET t.Ending_X = p.X, t.Ending_Y = p.Y
FROM #TempTable t, Table_1 p
WHERE p.ID IN (SELECT ID+1 FROM Table_1 where IsRepeat = 1)
AND p.ID-1 = t.ID
I think you need this
UPDATE t
SET Ending_X = X, Ending_Y = Y
FROM #TempTable t
WHERE t.ID IN (SELECT ID+1 FROM Table_1 where IsRepeat = 1))
How about unioning the two queries
INSERT INTO #TempTable (ID, CId, TagId, Beginning_X, Beginning_Y)
SELECT ID, CId,TagId, X, Y
from Table_1
WHERE IsRepeat = 1
UNION
SELECT Convert(Null, int) AS ID, Convert(Null, tinyint) AS CId,
Convert(Null, int) AS TagId, X,Y
FROM Table_1 t
WHERE t.ID IN (SELECT ID+1 FROM Table_1 where IsRepeat = 1))