Insert into select, target data unaffected - sql

We have a simple query
INSERT INTO table2
SELECT *
FROM table1
WHERE condition;
I can read somewhere that to use INSERT INTO SELECT statement, the following condition must be fulfilled:
The existing records in the target table are unaffected
What does it mean?

INSERT is a SQL operations that add some new rows into your table, with not affect on the others. This is happening instead of UPDATE operations, that cand affect multiple rows from your table if you use a wrong WHERE Clause.

Related

Execute result from subquery in a merge into statement

I have a query that has as the output the following table (2 columns). What it means, is that I'm going to use the result to wrap it inside a merge into statement.
INSERT_COLUMNS UPDATE_COLUMNS
BANK_NAME target.BANK_NAME = source.BANKNAME
What I'm talking about is this:
with sql_prepare_merge as (
SELECT *
FROM another_table
),
MERGE INTO bank_raw AS target
USING bank AS source
ON source.id = target.id
WHEN MATCHED THEN
UPDATE SET (select update_columns from sql_prepare_merge)
WHEN NOT MATCHED THEN
INSERT (select insert_columns from sql_prepare_merge)
VALUES (source.id, (select insert_columns from sql_prepare_merge));
Keep in mind that the "sql_prepare_merge" is the name from the CTE where I'm getting the table I shared with you - and it has much more code in it, but they don't help here. So, I'm planning to take the text resulting from the subquery and insert it inside the merge statement.
So far, the error I'm getting is: syntax error line 19 at position 4 unexpected 'WHEN'.. By the way, this is inside Snowflake.
Unfortunately this is not possible as per my understanding of the docs: https://docs.snowflake.com/en/sql-reference/sql/merge.html#notmatchedclause-for-inserts
In the non matched clause for inserts you can specify only such values/expressions, refer to the source relations. This means you somehow need to adjust your source part itself (e.g. by joining the initial source with another_table). If this is not possible, you would need to go for separate INSERT and UPDATE statements.

SQL Insert Query With Condition

I am trying to insert values into 1 column of a table when a condition is satisfied.
Note: The table already contains data for all the columns but for 1 which is empty. I would like to insert value into this 1 column depending on the WHERE clause.
I have this query:
INSERT INTO <TABLE_NAME>
(COLUMN_NAME)
(VALUE)
WHERE <CONDITION>
I am getting an exception:
Incorrect Syntax Near WHERE Keyword
I am able to do this using UPDATE:
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
But was wondering why the INSERT query was failing. Any advise appreciated.
As I understand your problem, you already have data in one row, and one column in that row does not have value, so you want to add value in to that column.
This the scenario for Update existing row, not the insert new row. You have to use UPDATE clause when data already present and you want to modify record(s). Choose insert when You want to insert new row in table.
So in your current scenario, Update Clause is your friend with Where Clause as you want to modify subset of records not all.
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
INSERT Clause does not have any Where Clause as per any RDBMS syntax(I think). Insert is condition less sql query, While SELECT, UPDATE, DELETE all are conditional commands, you can add Where Clause in all later ones.
In order to add a value into the one column when the rows are already populated, you will need to use the update statement.
If you need to insert a new row that has a where clause, you will need to use an insert into select statement:
INSERT INTO <table> (<columns>)
SELECT <columns>
FROM <table>
WHERE <condition>;
The SQL Insert dont accept where parameters, you could check this: SQL Insert Definition...
I do not know the whole question of what you want to do, but just using the INSERT statement is not possible, however it is possible to condition the insertion of data into a table, if this data is dependent on another table or comes from another table ... check here... SQL Insert explain in wikipedia
like this:
Copying rows from other tables
INSERT INTO phone_book2
SELECT *
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
or
INSERT INTO phone_book2 ( [name], [phoneNumber] )
SELECT [name], [phoneNumber]
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
Based on your question I have the feeling that you are trying to UPDATE a column in a table rather than insert.
Something like:
UPDATE column SET value WHERE different_column_value = some_value
I know this is kinda late, for those who still want to use the where clause in an insert query, it's kinda possible with a hack.
My understanding is that, you want to insert only if a condition is true. Let's assume you have a column in your database "surname" and you want to insert only if a surname doesn't exist from the table.
You kinda want something like INSERT INTO table_name blha blha blah WHERE surname!="this_surname".
The solution is to make that cell unique from your admin panel.
Insert statement will insert a new record. You cannot apply a where clause to the record that you are inserting.
The where clause can be used to update the row that you want.
update SET = where .
But insert will not have a where clause.
Hope this answers your question
INSERT syntax cannot have WHERE clause. The only time you will find INSERT has WHERE clause is when you are using INSERT INTO...SELECT statement.
I take it the code you included is simply a template to show how you structured your query. See the SO questions here, here and the MSDN question here.
In SQL Server (which uses Transact-SQL aka T-SQL) you need an UPDATE query for INSERT where columns already have values - by using the answer #HaveNoDisplayName gave :)
If you are executing INSERT / UPDATE from code (or if you need it regularly) I would strongly recommend using a stored procedure with parameters.
You could extend the procedure further by adding an INSERT block to the procedure using an IF-ELSE to determine whether to execute INSERT new record or UPDATE an existing, as seen in this SO answer.
Finally, take a look at SQLFiddle for a sandbox playground to test your SQL without risk to your RDMS :-)
Private case I found useful: Conditional insert which avoids duplications:
-- create a temporary table with desired values
SELECT 'Peter' FirstName, 'Pan' LastName
INTO #tmp
-- insert only if row doesn't exist
INSERT INTO Persons (FirstName, LastName)
SELECT *
FROM #tmp t
WHERE NOT EXISTS (SELECT * FROM Persons where FirstName=t.FirstName and LastName=t.LastName)
If the data need to be added for a column for an existing row then it’s UPDATE.
INSERT is creating a new row in the table.
For conditional INSERT, you can use the MERGE command.

OUTPUT Clause in Sql Server (Transact-SQL)

I Know that OUTPUT Clause can be used in INSERT, UPDATE, DELETE, or MERGE statement. The results of an OUTPUT clause in a INSERT, UPDATE, DELETE, or MERGE statements can be stored into a target table.
But, when i run this query
select * from <Tablename> output
I didn't get any error. The query executed as like select * from tablename with out any error and with same no. of rows
So what is the exact use of output clause in select statement. If any then how it can be used?
I searched for the answer but i couldn't find a answer!!
The query in your question is in the same category of errors as the following (that I have also seen on this site)
SELECT *
FROM T1 NOLOCK
SELECT *
FROM T1
LOOP JOIN T2
ON X = Y
The first one just ends up aliasing T1 AS NOLOCK. The correct syntax for the hint would be (NOLOCK) or ideally WITH(NOLOCK).
The second one aliases T1 AS LOOP. To request a nested loops join the syntax would need to be INNER LOOP JOIN
Similarly in your question it just ends up applying the table alias of OUTPUT to your table.
None of OUTPUT, LOOP, NOLOCK are actually reversed keywords in TSQL so it is valid to use them as a table alias without needing to quote them, e.g. in square brackets.
OUTPUT clause return information about the rows affected by a statement. OUTPUT Clause is used along with INSERT, UPDATE, DELETE, or MERGE statements as you mentioned. The reason it is used is because these statements themselves just return the number of rows effected not the rows effected. Thus the usage of OUTPUT with INSERT, UPDATE, DELETE, or MERGE statements helps the user by returning actual rows effected.
SELECT statement itself returns the rows and SELECT doesn't effect any rows. Thus the usage of OUTPUT clause with SELECT is not required or supported. If you want to store the results of a SELECT statement into a target table use SELECT INTO or the standard INSERT along with the SELECT statement.
EDIT
I guess I misunderstood your question. AS #Martin Smith mentioned its is acting an alias in the SELECT statement you mentioned.
IF OBJECT_ID('tempdelete') IS NOT NULL DROP TABLE tempdelete
GO
IF OBJECT_ID('tempdb..#asd') IS NOT NULL DROP TABLE #asd
GO
CREATE TABLE tempdelete (
name NVARCHAR(100)
)
INSERT INTO tempdelete VALUES ('a'),('b'),('c')
--Creating empty temp table with the same columns as tempdelete
SELECT * INTO #asd FROM tempdelete WHERE 1 = 0
DELETE FROM tempdelete
OUTPUT deleted.* INTO #asd
SELECT * FROM #asd
This is how you can put all the deleted records in to a table. The problem with that is that you have to define the table with all the columns matching the table from which you are deleting. This is how i do it.

Filtering duplicate records while importing data from source table to target table

This may be a simple query to some of you. But I am not strong in Sql, so expecting some solution for my problem.
I have 2 tables, ProductVenueImport and SupplierVenueImport.
We are dumping all the records from SupplierVenueImport to ProductVenueImport using MERGE clause and a Temp table. Temp will have valid records from SupplerVenuImport and from Temp table we are importing records to ProductVenueImport.
But before importing data to ProductVenueImport from Temp table I need to check for the duplicate records in my target (ProductVenueImport).
For example if I am importing a record with name as 'A', I need to look into ProductVenueImport whether 'A' already existing or not. If it is not existing then only I need to insert 'A' otherwise not.
Could somebody tell me how to do this?
Is using Cursors only the option?
Thanks,
Naresh
Assuming the Temp table itself doesn't have duplicates, you could use MERGE like this:
Insert non-existing products.
Do a NO-OP in case of an existing product.
Use $action in the OUTPUT clause to mark which rows were considered for insertion (and inserted) and which for update (but not really updated).
This is what I mean:
DECLARE #noop int; -- needed for the NO-OP below
MERGE INTO ProductVenueImport AS tgt
USING Temp AS src
ON src.ProductID = tgt.ProdutID
WHEN NOT MATCHED THEN
INSERT ( column1, column2, ...)
VALUES (src.column1, src.column2, ...)
WHEN MATCHED THEN
UPDATE SET #noop = #noop -- the NO-OP instead of update
OUTPUT $action, src.column1, src.column2, ...
INTO anotherTempTable
;
I think this would do this :
INSERT INTO PRODUCTTBL(FEILD1, FIELD2, FIELD3, FIELD4, FIELD5)
SELECT (FIELD1,FIELD2,FIELD3,FIELD4,FIELD5) FROM TEMP WHERE CRITERIAFIELD NOT IN(SELECT DISTINCT CRITERIAFIELD FROM PRODUCTTBL)
This should allow you to check for duplicates in a table
select columnname from tablename
group by columnname
having count(columnname) >1
sorry if I am not getting the question right, can't you use the merge statement on the source table with "When not matched Insert" to insert the new records alone
so in your case it should be like this
merge into ProductVenueImport using temp on (<condition for duplicate>)
when not matched then insert <clause>;
the merge clause will make sure that no duplicate records are inserted into your source table.

SQL Server INSERT trigger how to get data of current row

I've never created a trigger before and I'm trying to read online but am a little confused.
I want to create a trigger on a table that on insert, it will grab some data from different columns and insert it into a few different other tables.
I'm not sure how to write the T-SQL to get the data from the columns..
insert into [othetTable]
values ([col1 from row that was inserted], [col5 from row that was inserted])
What would the syntax be to get those values?
thanks
Use the inserted virtual table that is available to triggers. Note that there could be multiple rows in this table - your trigger could be processing multiple inserts at once.
Therefore, you need to use something like the following syntax:
insert into othertable
select col1, col5
from inserted
This will insert a row into othertable for each inserted row.