OUTPUT Clause in Sql Server (Transact-SQL) - 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.

Related

Clickhouse deleting data with WHERE

I am trying to delete some data using WHERE, note that I need 2 tables in order to identify the rows that should be deleted, so I need to join them, I thought of something like:
ALTER TABLE sample_db.test_first_table DELETE WHERE
(
SELECT s.value
FROM sample_db.test_first_table ft
JOIN sample_db.test_second_table st ON (ft.value=st.value)
WHERE `EXPRESSION HERE`
)
I understood that this Alter operation is a mutation, so when checking system.mutations table I see there is this fail reason: Code: 125, e.displayText() = DB::Exception: Scalar subquery returned more than one row
I checked that the expression I am writing is fine with a simple SELECT statement, so I am out of ideas how I can delete multiple rows based on an expression, any help is much appreciated
First of all: MUTATIONS are admin operations. They cannot be used on daily bases.
ALTER TABLE sample_db.test_first_table DELETE WHERE
value in
( SELECT value
from sample_db.test_second_table
WHERE `EXPRESSION HERE`
)

Insert into select, target data unaffected

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.

Bulk Insert with Table Valued Parameter not working

Need to insert multiple records into a SQL table. If there are duplicates (already inserted records) then I want to ignore them. For sending multiple records from my code to SQL, I am using table valued parameter.
Below is the query. It works during the first insertion when there are no rows in the table. On subsequent insert, no rows are added.
#tvpNewFMdata is the table valued parameter.
INSERT INTO
[dbo].[FMData]
(
[Id],
[Name],
[Path],
[CreatedDate],
[ModifiedDate]
)
SELECT
fm.Id, fm.Name, fm.Path, GETUTCDATE(), GETUTCDATE()
FROM
#tvpNewFMdata AS fm
WHERE
NOT EXISTS
(
SELECT
tbl.[Id]
FROM
[dbo].[FMdata] AS tbl
WHERE
tbl.Id = fm.Id
)
I am unable to locate as to what the cause that the first time insertion works but not the second time.
Tried with even removing the WHERE NOT EXISTS clause and it was only working in the first insertion. Subsequent insertion is not adding any rows to the table.
Is there an error, or just no rows inserted? If there are just no rows being inserted, even with the removed where clause, it sounds like you might be having problems populating the table value param. Have you watched what you are sending into SQL via a breakpoint or SQL Server Profiler?
Instead of where exists, have you tried a left join to fmData, and only inserting where the fmData row is null?
I agree with Damien, this is not bulk insert.
Sorry. My apologies. It was a mistake in my code. There was no issue in the SPROC. I was parameterizing the function and was passing the wrong table valued parameter.

Push deleted items into temporary table after MERGE

A simple query on the INTO clause. When i try the below statement, the items get pushed into CustomersBackup2013 whether the table exists or not.
SELECT *
INTO CustomersBackup2013
FROM Customers;
However, when i try using the into clause in a MERGE like
MERGE TargetTable tt
USING SyncTable st on <condition>
.
.
WHEN Not MATCHED BY SOURCE
DELETE
OUTPUT deleted.* INTO #Sometemptable;
I get an error saying invalid object name '#Sometemptable'
Isnt it supposed to create the table if it does not exist? Is there something I am doing wrong.
Is there any way i can modify the clause to push items into #Sometemptable?
No, the table has to exists for the output clause to work.
First create the #temp table and then you can output deleted values in it. Columns in the temp table must match columns from output by ordinal and type.
select into table creates a table if required. it is much like oracle's create table as select. see here select into table
merge only inserts, updates or deletes

How to get last inserted row from a table?

I tried below query but results in more than one row and [SCOPE_IDENTITY] as NULL.What are the alternates?
SELECT TOP 1000
[RTID],xxx,xxx
FROM [RouteTiming]
GO
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
GO
SELECT ##IDENTITY AS [##IDENTITY];
GO
Depending on the server version (SQL Server 2005+) you can use the OUTPUT clause:
INSERT INTO tablename (column names)
OUTPUT --this is where you put your select statement to get returned IDs etc.
VALUES (values in here, or you can use a select statememt as per usual)
MSDN Article: OUTPUT Clause (Transact-SQL)
If you are inside a stored procedure or a function, you can use INSERTED table (there is also a DELETED table) which is stored in memory until the scope is completed.
Once you have performed your insert, you can join the inserted table just like any other as long as it is within the same scope. I believe the inserted table has been around since SQL Server 2000, but it is definitely in 2005+.
MSDN Examples: Use the inserted and deleted Tables