Is there a way to conditionally use default column values in an INSERT..SELECT statement?
-
23-09-2019 - |
문제
I've got code similar to the following in a stored procedure that inserts a row into a table, I'd like to set the last column (FieldD) to @prmSomeValue unless it is null, otherwise just use the default value defined for that column.
IF (@prmSomeValue IS NULL)
INSERT INTO MyTable (fieldA,FieldB,FieldC)
SELECT A,B,C
FROM MyOtherTable
ELSE
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,@prmSomeValue
FROM MyOtherTable
This works, but violates the DRY principle. I'm trying to find some way to do this with a single insert statement. Something along the lines of the following pseudocode.
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,ISNULL(@prmSomeValue,DEFAULT)
FROM MyOtherTable
Anyone have any ideas?
Update - One more twist
The default constraint is not a literal value, but a function as shown below.
...DEFAULT (suser_sname()) FOR [FieldD]
Update
I finally punted and chose the lesser of evils and just copied the default value function into my query instead of falling through to the default configured for the column. I don't love it, but it gets the job done with less repetition in my query.
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,ISNULL(@prmSomeValue,suser_sname())
FROM MyOtherTable
해결책
Since essentially this is what SQL Server is doing, you could do something like this to at least avoid two nearly identical statements (pseudo-code):
INSERT (columnA,B,C) ... ;
IF @prmSomeValue IS NOT NULL
UPDATE ... ;
I don't think there is a way to COALESCE with the default value.
다른 팁
I would say your method is fine. A simple check followed by one insert. If you are worried about DRY, encapsulate the call so that it be called repeatedly.
I would say that inserts/updates on a db may be costly on some tables (depends on the design goal) so if you have to write extra code to to handle this scenario then I see no problem with the trade off.
This might work, depends on if you mean the default value defined in a default constraint, or in code? If "constraint" it fails, if "code" it works. Edit: you mean constraint. doh!
SELECT A,B,C,@prmSomeValue
FROM MyOtherTable
WHERE @prmSomeValue IS NOT NULL
UNION ALL
SELECT A,B,C,DEFAULT
FROM MyOtherTable
WHERE @prmSomeValue IS NULL
Which ever way you want to do it, specifying a column in the INSERT clause requires a value.
So your first solution is what you have do...
Something like this might work (tho not very pretty):
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,
case when @prmSomeValue is null
then
(SELECT text FROM syscomments WHERE id IN (SELECT cdefault FROM syscolumns
WHERE id = object_id('MyTable') AND cdefault > 0))
else @prmSomeValue
end
FROM MyOtherTable