This question already has answers here:
Using IF EXISTS with a CTE
(5 answers)
Closed 5 years ago.
I have a table-valued function that selects rows as part of a CTE, and I then want to perform a different select/insert into the returned table if no rows were selected in the CTE:
WITH myCte AS (SELECT * FROM abc WHERE xyz = 123)
IF NOT EXISTS (SELECT * FROM myCte)
BEGIN
...
END
However I'm getting a syntax error whenever I go to use CTE tables in the NOT EXISTS condition. My myCte is a lot more complex than the example, so it will be awkward to place the whole query in the condition.
How can I use the CTE result in the condition check?
You need to declare your common table expression in the context where it will be used and it can only be used for the statement that follows with. If you want to use the results multiple times, you can either repeat the common table expression multiple times, or you can use a table variable or temporary table to hold the results instead.
WITH myCte AS (SELECT * FROM abc WHERE xyz = 123)
select *
into #myTempTable
from myCte
IF NOT EXISTS (SELECT * FROM #myTempTable)
BEGIN
...
END
Related
This really silly question just popped out of my mind out of curiosity; i'm still learning how to write better code in SQL and i just found myself in the situation where i have to check if the result of a query exists and then, if that was true, execute the same exact query to create a new table.
The code is working and considering i'm not dealing with large amounts of data i have no problems of computation times but...it's simply ugly and i would like to make it more...appealing?
This is the code i'm refering to:
[...]
IF EXISTS (SELECT *value*, COUNT(*) AS Repetitions
FROM *table*
GROUP BY *value*
HAVING COUNT(*) > 1)
SELECT *value*, COUNT(*) AS Repetitions
INTO dbo.*newtable*
FROM *table*
GROUP BY *data*
HAVING COUNT(*) > 1
ELSE
[...]
Doing an exists first is unecessary.
Simply do
select <columns> into NewTable
From Table
where criteria;
if ##rowcount=0
begin
drop table NewTable;
end
else
begin
/* Actions if table created */
end
I have a CTE I am using to pull some data from two tables then stick in an intermediate table called cte_list, something like
with cte_list as (
select pl.col_val from prune_list pl join employees.employee emp on pl.col_val::uuid = emp.id
where pl.col_nm = 'employee_ref_id' limit 100
)
Then, I am doing an insert to move records from the cte_list to another archive table (if they don't exist) called employee_arch_test
insert into employees.employee_arch_test (
select * from employees.employee where id in (select col_val::uuid from cte_list)
and not exists (select 1 from employees.employee_arch_test where employees.employee_arch_test.id=employees.employee.id)
);
This seems to work fine. The problem is when I add another statement after, to do some deletions from the main employee table using this aforementioned cte_list - the cte_list apparently no longer exists?
SQL Error [42P01]: ERROR: relation "cte_list" does not exist
the actual delete query:
delete from employees.employee where id in (select col_val::uuid from cte_list);
Can the cte_list CTE table only be used once or something? I'm running these statements in a LOOP and I need to run the exact same calls for about 2 or 3 other tables but hit a sticking point here.
A CTE only exists for the duration of the statement of which it's a part. I gather you have an INSERT statement with the CTE preceding it:
with cte_list
as (select pl.col_val
from prune_list pl
join employees.employee emp
on pl.col_val::uuid = emp.id
where pl.col_nm = 'employee_ref_id'
limit 100
)
insert into employees.employee_arch_test
(select *
from employees.employee
where id in (select col_val::uuid from cte_list)
and not exists (select 1
from employees.employee_arch_test
where employees.employee_arch_test.id = employees.employee.id)
);
The CTE is part of the INSERT statement - it is not a separate statement by itself. It only exists for the duration of the INSERT statement.
If you need something which lasts longer your options are:
Add the same CTE to each of your following statements. Note that because data may be changing in your database each invocation of the CTE may return different data.
Create a view which performs the same operations as the CTE, then use the view in place of the CTE. Note that because data may be changing in your database each invocation of the view may return different data.
Create a temporary table to hold the data from your CTE query, then use the temporary table in place of the CTE. This has the advantage of providing a consistent set of data to all operations.
This question already has answers here:
Update a table using JOIN in SQL Server?
(13 answers)
Closed 7 years ago.
I am VERY rusty with my SQL, it's been a few years, but I need to write a query to fix something in a table I have.
There are erroneous duplicates where not every column is the same, but I know at least one is.
So I have this query that works:
SELECT
[IntMsgID], [SortDate], COUNT(*)
FROM
[databasename].[dbo].[tblDoc]
GROUP BY
[IntMsgID], [SortDate]
HAVING
COUNT(*) >= 2
AND [IntMsgID] IS NOT NULL
It identifies the documents in question. What I need to do, then, is take the results from that and update another field simply with the value of Y or 1.
I've done searching and it seems any query I've tried to plug in fails, such as
UPDATE [databasename].[dbo].[tblDoc] AS t
INNER JOIN
(SELECT [IntMsgID] msgid
FROM [databasename].[dbo].[tblDoc]
GROUP BY [IntMsgID]) t1 ON t.[IntMsgID] = t1.[IntMsgID]
SET [JG_SQLDupe] = 'Y'
I get syntax errors at "AS" and "INNER" and "t1"
I would use a CTE to achieve this:
;with updts as (SELECT [IntMsgID], [SortDate], count(*)
FROM [databasename].[dbo].[tblDoc]
Group By [IntMsgID], [SortDate]
HAVING count(*) >= 2 AND [IntMsgID] is not null)
update t
set t.Flag = 'Y'
from [databasename].[dbo].[tblDoc] t inner join
updts u on t.[IntMsgID] = u.[IntMsgID]
and t.[SortDate] = u.[SortDate]
Why is this legal:
DECLARE #Party TABLE
(
PartyID nvarchar(10)
)
INSERT INTO #Party
SELECT Name FROM
(INSERT INTO SomeOtherTable
OUTPUT inserted.Name
VALUES ('hello')) [H]
SELECT * FROM #Party
But the next block gives me an error:
WITH Hey (Name)
AS (
SELECT Name FROM
(INSERT INTO SomeOtherTable
OUTPUT inserted.Name
VALUES ('hello')) [H]
)
SELECT * FROM Hey
The second block gives me the error "A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed in a SELECT statement that is not the immediate source of rows for an INSERT statement.
It seems to be saying thst nested INSERT statements are allowed, but in my CTE case I did not nest inside another INSERT. I'm surprised at this restriction. Any work-arounds in my CTE case?
As for why this is illegal, allowing these SELECT operations with side effects would cause all sorts of problems I imagine.
CTEs do not get materialised in advance into their own temporary table so what should the following return?
;WITH Hey (Name)
AS
(
...
)
SELECT name
FROM Hey
JOIN some_other_table ON Name = name
If the Query Optimiser decided to use a nested loops plan and Hey as the driving table then presumably one insert would occur. However if it used some_other_table as the driving table then the CTE would get evaluated as many times as there were rows in that other table and so multiple inserts would occur. Except if the Query Optimiser decided to add a spool to the plan and then it would only get evaluated once.
Presumably avoiding this sort of mess is the motivation for this restriction (as with the restrictions on side effects in functions)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc.
SELECT * FROM tbl1
and
SELECT field1, field2,...... FROM tbl1
how does SQL engine execute the previous two select statements (step by step) and which one performs better?
Simple answer: * is slow, named fields are fast.
Fewer named fields are faster.
Smaller datafields are faster than bigger ones.
Never select blobs of you do not have to.
Have a look in this old Answered post about:
Select * vs Select Column
Regards
In case of MySQL even a column order matters (and its order in table definition).