Question

I am a newb to SQL since I can normally get away with simple queries/migrations without digging into it, however I have a more complex one that doesn't involve a join and I am wondering how I delete when there is a foreign constraint without using on cascade. Here's my query. I could not find a good answer from googling.

WITH aDeleteVariable AS (SELECT TOP 1 FooID as id FROM [BSystem].[Foo].[bar] order by      
CreateTimeUTC desc)
DELETE FROM [BSystem].[Foo].[fooBar] where FooID = id
DELETE FROM [BSystem].[Foo].[bar] where FooID = id

So I need to delete [BSystem].[Foo].fooBar first, then [BSystem].[Foo].[bar] This will be executed at run time so it cannot be hard coded. "1" is really going to be n, however I have that code worked out.

I get invalid column name 'id' when trying to execute this query. How can I fix it?

Was it helpful?

Solution

Your DELETE statements don't reference aDeleteVariable. The id column only exists in the context of aDeleteVariable.

You need to join aDeleteVariable into your DELETE statements. Also, you can't reuse the common table expression, so you have to duplicate it.

See this SQL Fiddle (with simplified schema/table names), but below is what you want.

WITH aDeleteVariable AS (SELECT TOP 1 FooID as id
        FROM [BSystem].[Foo].[bar] order by CreateTimeUTC desc)
DELETE FB 
        FROM [BSystem].[Foo].[fooBar] AS FB
        INNER JOIN aDeleteVariable AS DV ON (FB.FooID = DV.id);
WITH aDeleteVariable AS (SELECT TOP 1 FooID as id
        FROM [BSystem].[Foo].[bar] order by CreateTimeUTC desc)
DELETE B
        FROM [BSystem].[Foo].[bar] AS B
        INNER JOIN aDeleteVariable AS DV ON (B.FooID = DV.id);

Of course, with joining to aDeleteVariable, you don't need the id alias. The following will work.

WITH aDeleteVariable AS (SELECT TOP 1 FooID
        FROM [BSystem].[Foo].[bar] order by CreateTimeUTC desc)
DELETE FB 
        FROM [BSystem].[Foo].[fooBar] AS FB
        INNER JOIN aDeleteVariable AS DV ON (FB.FooID = DV.FooID);
WITH aDeleteVariable AS (SELECT TOP 1 FooID
        FROM [BSystem].[Foo].[bar] order by CreateTimeUTC desc)
DELETE B
        FROM [BSystem].[Foo].[bar] AS B
        INNER JOIN aDeleteVariable AS DV ON (B.FooID = DV.FooID);

Given that there are two separate common table expressions, there is a race condition, and the second expression might return a different FooID (or multiple when you adapt this to N records). You might want to select your IDs into a table variable instead of using a common table expression. The following should work.

DECLARE @DeleteVariable TABLE (FooID INT);
INSERT INTO @DeleteVariable (FooID)
        SELECT TOP 1 FooID FROM [BSystem].[Foo].[bar]
                ORDER BY CreateTimeUTC DESC;
DELETE FB 
        FROM [BSystem].[Foo].[fooBar] AS FB
        INNER JOIN @DeleteVariable AS DV ON (FB.FooID = DV.FooID);
DELETE B
        FROM [BSystem].[Foo].[bar] AS B
        INNER JOIN @DeleteVariable AS DV ON (B.FooID = DV.FooID);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top