Delete rows from CTE in SQL SERVER - sql

I have a CTE which is a select statement on a table. Now if I delete 1 row from the CTE, will it delete that row from my base table?
Also is it the same case if I have a temp table instead of CTE?

Checking the DELETE statement documentation, yes, you can use a CTE to delete from and it will affect the underlying table. Similarly for UPDATE statements...
Also is it the same case if I have a temp table instead of CTE?
No, deletion from a temp table will affect the temp table only -- there's no connection to the table(s) the data came from, a temp table is a stand alone object.

You can think of CTE as a subquery, it doesn't have a temp table underneath.
So, if you run delete statement against your CTE you will delete rows from the table. Of course if SQL can infer which table to upadte/delete base on your CTE. Otherwise you'll see an error.
If you use temp table, and you delete rows from it, then the source table will not be affected, as temp table and original table don't have any correlation.

In the cases where you have a sub query say joining multiple tables and you need to use this in multiple places then both cte and temp table can be used. If you however want to delete records based on the sub query condition then cte is the way to go. Sometimes you can simply use the delete statement with out a need of cte since it's a delete statement and only rows that satisfy the query conditions get deleted even though multiple conditions are used for filtering.

Related

Executing an insert query on successful deletion in postgres

Is it possible to insert some data into one table if some entry is deleted in another table?
I am able to do that with multiple queries(delete first, then insert by checking if it exists). But this runs as two queries. Is it possible to merge the queries or what is the most efficient way of doing this?
WITH deleted_rows AS (
DELETE FROM users
WHERE
id = 15
RETURNING *
)
INSERT INTO users_history (SELECT * FROM deleted_rows);
I explain my answer:
RETURNING * return table records such as select * from command, but return only deleted records. This RETURNING command you can use after the INSERT or UPDATE command too. The WITH query being CTE (Common Table Expression) query, is particularly useful when the subquery is executed multiple times. It is equally helpful in place of temporary tables. It computes the aggregation once and allows us to reference it by its name (maybe multiple times) in the queries. So finally we use SELECT * FROM deleted_rows query which will return all deleted records and using INSERT INTO users_history query we can insert all these return records to the new user_history table.

Remove the duplicates expect one record in SQL Server

Here I wanted to delete all records with value 1 and only keep a single record
Without knowing your DBMS it's really tough to know which query you need. If your dbms supports cte and row_number() then below query will work.
with cte as
(select *,row_number()over(order by column_1)rn from table_name)t
delete cte where rn>1
In SQL Server this will work fine.
Given the nature of your data, I would suggest removing all rows and adding a new one back in:
truncate table t;
insert into t(column_1)
values (1);
Be careful! The truncate table removes all rows from the table.

about CTE and physically deleting records from table

For deleting duplicate records I have found below query on stack overflow which works fine.In this query we are deleting records from "a" and not from tblEmployee.So my question is how duplicate records get physically deleted from physical table though we don't have any unique or primary key.
WITH a as (
SELECT Firstname,ROW_NUMBER() OVER(PARTITION by Firstname, empID ORDER BY Firstname)
AS duplicateRecCount
FROM dbo.tblEmployee
)
--Now Delete Duplicate Records
DELETE
FROM a
WHERE duplicateRecCount > 1
Inorder to understand this, let's consider one of the differences between temp tables and CTE.
When we use Temporary tables, this temp table will be saved in a Tempdb database. So, it is just a copy of your table tblEmployee. No matter what changes you make to temp table, it won't affect tblEmployee.
But, when you use cte, it is actually pointing to the same table itself. That is why, if you delete from cte, it will affect tblEmployee also.
CTE is nothing but a disposable view.
You appear to be using an updatable CTE in SQL Server. In this case, the CTE acts the same as a view.
The view is updatable because it refers to only one table and does not have aggregation. Hence, the effect of the CTE is merely to add columns to the table, tables which can be referenced in the DELETE statement.
The conditions for an updatable view are explained in the documentation. These conditions are the same as for your CTE.

PostgreSQL return select results AND add them to temporary table?

I want to select a set of rows and return them to the client, but I would also like to insert just the primary keys (integer id) from the result set into a temporary table for use in later joins in the same transaction.
This is for sync, where subsequent queries tend to involve a join on the results from earlier queries.
What's the most efficient way to do this?
I'm reticent to execute the query twice, although it may well be fast if it was added to the query cache. An alternative is store the entire result set into the temporary table and then select from the temporary afterward. That also seems wasteful (I only need the integer id in the temp table.) I'd be happy if there was a SELECT INTO TEMP that also returned the results.
Currently the technique used is construct an array of the integer ids in the client side and use that in subsequent queries with IN. I'm hoping for something more efficient.
I'm guessing it could be done with stored procedures? But is there a way without that?
I think you can do this with a Postgres feature that allows data modification steps in CTEs. The more typical reason to use this feature is, say, to delete records for a table and then insert them into a log table. However, it can be adapted to this purpose. Here is one possible method (I don't have Postgres on hand to test this):
with q as (
<your query here>
),
t as (
insert into temptable(pk)
select pk
from q
)
select *
from q;
Usually, you use the returning clause with the data modification queries in order to capture the data being modified.

Merge Statement Performance

I have one table with one column iscurrent, values are 0 and 1.
I am inserting rows to this table with a merge statement that is inserting or updating based on the value of iscurrent. For performance tuning I have created two partitions with 0 and 1 on that table. But the performance is not good enough.
How can I tune the merge statement? Every time it is merging thousands rows to million of rows. Will partitioning the table help?
If you're using a derived table as the source, start by tuning that select statement first, or put the results of the derived table into a physical table with the proper indexes.
MERGE myTargetTabe as TargetTable
USING (derived table statement goes here) SourceTable on .......
A merge statement will scan every row that meets the criteria you specify in the "ON" clause, if there are rows that you don't need to merge, then exclude the rows here. For example:
MERGE myTargetTabe as TargetTable
USING (derived table statement goes here) SourceTable on TargetTable.ID = SourceTable.ID and TargetTable.OtherColumn NOT IN (....) and ...... or .... and so on.