SQL Query GO Command after every 100th INSERT INTO - sql

I have a query that inserts about 60.000 records in a table, using SQL Server.
The 100th INSERT INTO-statement is followed by a GO-command. In total the query contains about 600 GO-commands. Is that really necessary, or can I just have one GO-command at the end with that many INSERT's?
Sample:
(...)
insert into myTable(T_id,T_key,T_value) VALUES(97,97,97)
insert into myTable(T_id,T_key,T_value, T_comment) VALUES(98,98,98,'hello')
insert into myTable(T_id,T_key,T_value, T_range) VALUES(99,99,99,'1-100')
insert into myTable(T_id,T_key,T_value) VALUES(100,100,100)
go
insert into myTable(T_id,T_key,T_value) VALUES(101,101,102)
insert into myTable(T_id,T_key,T_value, T_comment) VALUES(102,102,102,'next')
(...)
insert into myTable(T_id,T_key,T_value) VALUES(60000,60000,60000)
go
insert into subTable(S_id, S_key, S_ref_T) VALUES(1,'s1',(Select top 1 T_ref from myTable where T_id = 34)
insert into subTable(S_id, S_key, S_ref_T) VALUES(23,'s23',(Select top 1 T_ref from myTable where T_id = 6001)
(...)

Related

Merge not working for insert a record when it's doesn't exist

Can I use Merge to insert a record when it's doesn't exist like below,
MERGE INTO [dbo].[Test] AS [Target]
USING (SELECT DISTINCT [Name] FROM [dbo].[Test]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), 'Hello');
If the record with value Hello does not exists in table Test, insert it otherwise don't do anything. With above code record is not inserted even I don't have this record in table. And there are no errors.
I know how to accomplish this using insert ... where not exists (...) but am specifically wanting to know how to do it using a merge statement.
The reason your merge statement wasn't working is that you were merging the same table, dbo.Test, back onto itself, so of course there is no missing record.
You can insert a single missing record as follows, where you create a source query to contain the record(s) you wish to insert:
declare #Test table (id uniqueidentifier, [Name] nvarchar(64))
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
MERGE INTO #Test AS [Target]
USING (select 'Hello' [Name]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), [Name]);
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
-- C1C87CD5-F745-436D-BD8D-55B2AF431BED | Hello
I agree with the answer from Dale K. Its correct.
If I suppose you might have a source_table from where the data needs to get inserted and not to get inserted if the record already exists then you can do the following.
Instead of the MERGE you can
insert
into dbo.Test
(id
,name
)
select top 1
newID()
,'Hello'
from dbo.Test a
where not exists(select 1
from dbo.Test b
where b.name='Hello')

Referencing inserted ID in multiple insert transactions in Postgres

I need to build a SQL query that must be able to insert data in a first table, grab the inserted ID and then use it as foreign key in the following tables.
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
SELECT * FROM inserted; -- this has the inserted id
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', ???)
So how do I reference the id in inserted in the secondTable insert?
You have completed this 80% percent, the complete SQL is:
with inserted as (
insert into first_table(name) values ('somename') returning id
)
insert into second_table(name, foreign_id) select 'someexternalname',id from inserted
You can do this:
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
INSERT INTO secondTable (name, foreign_id)
SELECT
'someexternalname',
id
FROM inserted;
You can try this:
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', (SELECT
MAX (id) FROM firstTable))

Delete Result Rows from a Table in SQL

I have 2 tables named BM_Data1 & BM_Data1_May62019. Both Tables contains the same data as BM_Data1_May62019 is the copy of BM_Data1 table. But BM_Data1 has some extra rows, How can I delete those extra rows from BM_Data1 and make it same like BM_Data1_May62019.
I got the extra rows using the following query.
SELECT * FROM
(SELECT * FROM BM_DATA1
EXCEPT
SELECT * FROM BM_DATA1_MAY62019) a
There are 7803 extra rows, how can I delete them from BM_Data1 table?
Thank You
As you confirmed RECID is common in both table with unique value, you can try this following script
DELETE FROM BM_DATA1
WHERE RECID NOT IN
(
SELECT RECID FROM BM_DATA1_MAY62019
)
Use a MERGE statement with WHEN NOT MATCHED BY SOURCE THEN DELETE.
MERGE works like a JOIN of sorts, and you need to be able to identify which rows are equal. You do this by the ON clause - for you, that would be RECID.
I suggest you run these in a transaction first, so you verify that you only delete the data you intend to - and commit the transaction only when you are sure you have the right configuration. If something is wrong, you can rollback
BEGIN TRANSACTION
MERGE BM_DATA1 AS Target
USING BM_DATA1_MAY62019as Source
ON (Target.RECID = Source.RECID)
WHEN NOT MATCHED BY SOURCE
THEN DELETE;
SELECT * FROM BM_DATA1
-- ROLLBACK TRANSACTION -- Uncomment and use this if it deleted the wrong data
-- COMMIT -- Uncomment and use this if it deleted the right data!
I've included some DDL so you can run this for yourself to help you understand the example. The ID column is the one that is common to both tables and you are removing the rows in A that are not in B
create table #data_a( id int, val int)
create table #data_b( id int, val int)
insert into #data_a select 1, 1
insert into #data_a select 2, 4
insert into #data_a select 3, 5
insert into #data_a select 4, 5
insert into #data_a select 5, 5
insert into #data_a select 6, 5
insert into #data_a select 7, 5
insert into #data_a select 8, 5
insert into #data_b select 1, 1
insert into #data_b select 2, 4
insert into #data_b select 3, 5
insert into #data_b select 4, 5
insert into #data_b select 5, 5
-- delete the extra rows in A
delete a from #data_a as a
left join #data_b as b on a.id = b.id
where b.id is null
-- we can see the rows are no longer in B
select * from #data_a
select * from #data_b
drop table #data_a
drop table #data_b
create table t1(id int, demo int);
create table t2(id int, demo int);
insert into t1 values (1, 1);
insert into t2 values (1, 1);
insert into t1 values (2, 2);
insert into t2 values (2, 2);
insert into t1 values (3, 3);
insert into t2 values (3, 3);
insert into t1 values (4, 4); -- t1 table has some extra rows
insert into t1 values (5, 5); -- t1 table has some extra rows
insert into t1 values (6, 6); -- t1 table has some extra rows
To delete those records from first table which are not second table:
delete from t1 where id not in (select id from t2)
use just delete with a correlated subquery
delete from [BM_DATA1]
where not exists
(select 1
from [BM_DATA1_MAY62019]
where [BM_DATA1_MAY62019].RECID = [BM_DATA1].RECID -- put here here identified column name
)

Insert into 2 tables from a single select query using TSQL

I am trying to insert into 3 tables from one single select statement. Here is what I am trying to do:
insert into dbo.temp1 (name, location, city)
select name, location, city from mytable.
I want to be able to insert into 3 tables once I run the select statement like inserting into temp1, temp2 and temp3.
How can I do this? Thanks.
You can do it maximum for 2 tables with using output:
insert into dbo.temp1 (name, location, city)
output inserted.name, inserted.location, inserted.city into temp2
select name, location, city from mytable
You can't do this in one step*
What you can do is to insert the initial query into a #temp table (or a #table variable) as a staging area, and then insert into the tables from there. Wrap the steps in a transaction to retain ACID:
BEGIN TRAN
select name, location, city
into #TEMP
from mytable;
insert into temp1(name, location, city)
select name, location, city
from #TEMP;
-- Same for temp2 and temp3.
COMMIT TRAN
* Excluding hacks such as a view with an Instead-of Trigger.
The staging table is important from a concurrency point of view, as repeating the original query 3 times may result in different results if there are interim concurrent changes to the source table.
You can.
With a trick.
Create a view, then create an 'instead of' trigger for insert on that view where you insert the stuff into your tables. If you now insert into your view, you finally insert data in 3 tables. Here's a demo
-- 1. create 3 test tables
create table t1( id int, f1 varchar(20))
create table t2( id int, f2 varchar(20))
create table t3( id int, f3 varchar(20))
go
-- 2. create the view
create view Tt as
select t1.ID, t1.f1, t2.f2,t3.f3
from t1
join t2 on t1.ID=t2.ID
join t3 on t1.ID=t3.id
go
-- 3. create the trigger
create trigger Tr_Test on Tt INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into t1 select id,f1 from inserted
insert into t2 select id,f2 from inserted
insert into t3 select id,f3 from inserted
END
GO
-- 4. now do your insert with a single select
insert into tt
select 1,'A','B','C'
-- 5. and watch the 3 tables
select * from t1
select * from t2
select * from t3
voilá, one insert, 3 tables got modified. Wwe don't count the hidden trigger, do we ;-)
There is no way to insert into X tables with one query (Ok it its with insert and output to table).
So you have to write 3 queries.
Or you can generate SQL statments with dynamic queries.
I don't believe you can insert into multiple tables in one statement. You can definitely do it in one transaction, however.
BEGIN TRANSACTION
INSERT INTO dbo.temp1 (name, location, city)
SELECT name, location, city
FROM myTable
INSERT INTO dbo.temp2 (name, location, city)
SELECT name, location, city
FROM myTable2
COMMIT TRANSACTION
You can insert into multiple tables with one select statement using a TRIGGER.
CREATE TRIGGER TEMP2_TEMP3_INSERT ON TEMP1
AFTER INSERT AS
BEGIN
/* create your insert statements for TEMP2 and TEMP3 here
referencing the data from the first insert */
END;
GO
MySQL doesn't support multi-table insertion in a single INSERT statement. Oracle is the only one I'm aware of that does, oddly...
However, you CAN use a transaction and have both of them be contained within one transaction.
MySQL:
START TRANSACTION;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server:
BEGIN TRAN;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server with error catching/rollback:
BEGIN TRANSACTION [Tran1]
BEGIN TRY
INSERT INTO table1 VALUES ('1','2','3')
INSERT INTO table2 VALUES ('1','2','3')
COMMIT TRANSACTION [Tran1]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1]
END CATCH
GO

Delete data using SQL Partitioning

I want to create a table implementing partition function such that if the number of records becomes 5+1 then the first recor gets deleted For example if the records are 1,2,3,4,5 and we insert 6th record then 1st record gets deleted and remaining records are 2,3,4,5,6
After your Insert you could add something like:
delete from mytable
where RecordID <= select(MAX(RecordID)-5 from mytable);
So that everything before the 5 most recent rows are deleted.
You could use a trigger after insert to delete the surplus rows. Try this example:
BEGIN TRANSACTION;
SET NOCOUNT ON;
create table t (id int identity(1,1), val char(1))
go
create trigger limit_t on t for insert as
begin
if (select count(*) from t) > 5
delete from t where id <= (select max(id)-5 from t);
end
go
-- insert five rows
insert t (val) values ('a'),('b'),('c'),('d'),('e')
-- insert a sixth and seventh row
insert t (val) values ('f'),('g')
-- retrieve content after last insert
select * from t
-- the table now holds values [c,d,e,f,g]
ROLLBACK TRANSACTION;