Why does my code not merge table 1 to the bottom of table 2? - sql

SELECT * INTO "2020_to_2021_divvy_tripdata"
FROM
(MERGE [PortfolioDB].[dbo].['202008-divvy-tripdata$'] as "202008"
USING [PortfolioDB].[dbo].['202007-divvy-tripdata$'] as "202007" on [202007].ride_id = [202008].ride_id
WHEN NOT MATCHED THEN
INSERT VALUES ([202008].*)
I want it to take the data from 202008 and merge it to 202007 so that the one table simply is merged to the bottom of the other, but it says Incorrect syntax near *. I have tried all my previous toolkits like changing square brackets combinations and such.
Both tables are formatted the same, with the column names matching.
I tried to emulate the code from here. Eventually, I will merge multiple months onto each other to create a full-year table.

Your INSERT VALUES() has two issues...
You should insert from [202007] (the source), not from [202008] (the destination)
You can't use [202007].*, you have to list all the columns individually
Then, you need an OUTPUT clause for the MERGE to make its data available to an outer query.
Here's a demo: db<>fiddle
Here's a potential re-write of your statement...
INSERT INTO
"2020_to_2021_divvy_tripdata"
SELECT
*
FROM
(
MERGE [PortfolioDB].[dbo].['202008-divvy-tripdata$'] as "202008"
USING [PortfolioDB].[dbo].['202007-divvy-tripdata$'] as "202007"
ON [202007].ride_id = [202008].ride_id
WHEN NOT MATCHED THEN
INSERT VALUES ([202007].x, [202007].y, [202007].z)
OUTPUT
inserted.*
)
merge_inserted

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.

Generate insert column based on select columns

I have a scenario, where 100's of select statements sql's are in one metadata table or some text file.
Need to insert all sql results into one specific table. (master table has col1, col2,col3 .... 200columns )
problem im facing(ORA-00947) is every select statement has different number of columns.
.. i need to generate INSERT PART.
CASE 1 : INSERT INTO (COL1,COL2,COL3) <<this select part comes from file/variable>>
CASE 2 : INSERT INTO (COL1) <<this select part comes from file/variable>>
CASE 3 : INSERT INTO (COL1) <<this select part comes from file/variable>>
have to figure out how many columns are in select part then generate INSERT part.
.
Thought of create as select but problem is some select statement has max(col) without alias so it will fail.
This is too long for a comment.
If you are storing SQL in a table, then you are constructing your query dynamically. So, update the table and list the columns that you want.
You could then construct the inserts as :
insert into master_table (<column list here>)
<select here>;
Both the select and column list would come from the table.
By far the easiest is to create a view for each SELECT statement. Then you can query the USER_TAB_COLUMNS view on the view name and get the column names.
Best regards,
Stew Ashton

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.

Difference between INSERT INTO and INSERT ALL INTO

While I was inserting some records in table i found that..
INSERT INTO T_CANDYBAR_DATA
SELECT CONSUMER_ID,CANDYBAR_NAME,SURVEY_YEAR,GENDER,1 AS STAT_TYPE,OVERALL_RATING
FROM CANDYBAR_CONSUMPTION_DATA
UNION
SELECT CONSUMER_ID,CANDYBAR_NAME,SURVEY_YEAR,GENDER,2 AS STAT_TYPE,NUMBER_BARS_CONSUMED
FROM CANDYBAR_CONSUMPTION_DATA;
79 rows inserted.
INSERT ALL
INTO t_candybar_data VALUES (consumer_id,candybar_name,survey_year,gender,1,overall_rating)
INTO t_candybar_data VALUES (consumer_id,candybar_name,survey_year,gender,2,number_bars_consumed)
SELECT * FROM candybar_consumption_data
86 rows inserted.
I have read somewhere that INSERT ALL INTO automatically unions then why those difference is showing.
The problem is your queries are different—your first is with UNION and your second is without—so they are naturally inserting different numbers of values. As far as what INSERT ALL is versus a straight INSERT:
INSERT can be used for inserting new records to a single table.
INSERT ALL can be used for inserting new records to multiple tables based on the query condition.
So your assumption as stated here:
I have read somewhere that INSERT ALL INTO automatically unions then
why those difference is showing.
Is incorrect. INSERT ALL doesn’t have anything to do with UNION in any way. But that said, you might be mixing up UNION ALL as explained here.
The SQL UNION ALL operator is used to combine the result sets of 2 or
more SELECT statements. It returns all rows from the query (even if
the row exists in more than one of the SELECT statements).
Each SELECT statement within the UNION ALL must have the same number
of fields in the result sets with similar data types.

Postgres serial values insertion

From the Postgres documentation on INSERT, default keyword should auto increment columns declared as serial.But when I combine it with select statement, it throws me an error
syntax error at or near "DEFAULT"
Here is the insert statement
insert into abc (id,date,serialnumber) (DEFAULT,select (data.date,data.serialnumber) from data)
DEFAULT can only be as a "literal" for an INSERT statement in the VALUES clause. I cannot be used inside the column list of a SELECT statement even if that is used for an INSERT.
To apply the default value, simply leave out the column:
insert into abc (date,serialnumber)
select date, serialnumber
from data
For an example see here: http://sqlfiddle.com/#!12/d291a/1
Also: do not put a column list into parantheses. (a,b) is something different than a,b in Postgres. The first is a single record with two attributes, the second are two different columns.
See this SQLFiddle demo here: http://sqlfiddle.com/#!12/3a890/1 and note the difference between the two results.