The last line of the following code inserts records from #S
to #D
if value is a valid date; otherwise it returns NULL (since I am not using ELSE
clause):
CREATE TABLE #S(COL VARCHAR(15))
INSERT #S VALUES('20250630'),('ABC'),('20150821')
CREATE TABLE #E(ERCOL VARCHAR(15))
CREATE TABLE #D(DTCOL DATE)
INSERT #D(DTCOL) SELECT (CASE WHEN ISDATE(COL) = 1 THEN (CAST(COL AS DATE)) END) FROM #S
Question: How can we include ELSE
block in the last line of above code and use that block to insert the error value (ABC
) into #E
table while still using the same SELECT statement as above. So, we are just modifying the last line of the above code:
INSERT #D(DTCOL) SELECT (CASE WHEN ISDATE(COL) = 1 THEN (CAST(COL AS DATE)) ELSE 'NEED TO INSERT "ABC" VALUE TO #E TABLE' END) FROM #S
1 Answer 1
Mostly
You can use this code to Do What You're AskingTM️, with a couple caveats. The first being that "bad" rows will be inserted with a canary value of 17530101
, and the second being that those rows will be deleted on subsequent executions of the MERGE
statement.
This should answer your question about doing it all in one statement via Composable DML©️, but it may be dissatisfying based on the caveats above.
If so, you'll want to break this up into two steps as suggested in various comments.
INSERT
#E(ERCOL)
SELECT
x.COL
FROM
(
MERGE
#D WITH (SERIALIZABLE) AS t
USING
(
SELECT
s.*,
m =
CASE
WHEN TRY_CAST(s.COL AS date) IS NOT NULL
THEN s.COL
ELSE CONVERT(date, '17530101')
END
FROM #S AS s
) AS s
ON s.m = CONVERT(date, '17530101')
WHEN NOT MATCHED
THEN
INSERT
(DTCOL)
VALUES
(s.m)
WHEN MATCHED
AND t.DTCOL = CONVERT(date, '17530101')
THEN DELETE
OUTPUT
$action AS a,
s.*
) AS x
WHERE x.m = CONVERT(date, '17530101');
-
Why the
SERIALIZABLE
hint?Yano_of_Queenscastle– Yano_of_Queenscastle2025年07月01日 21:33:57 +00:00Commented Jul 1 at 21:33
delete t output deleted.* into #E from #source t where t.SomeValue is wrong
and insert the correct values later