SQL Server EXEC a raw SQL query inside of the SELECT statement - sql

I have a table, which contains an external table name where I can find a value that I need (that table doesn't have any PKs/FKs, I can not change this).
The thing is, is it possible to execure a dynamic SQL query inside of the SELECT statement ?
Something like
SELECT Col1,
Col2,
'SELECT TOP 1 Col from ' + Col3,
FROM Table1

I'm not sure if this is exactly what you are looking to do, but this might be a solution if the value you would like to concatenate is going to be the same (which it looks like from the TOP 1 in the example):
IF OBJECT_ID('atest') IS NOT NULL
DROP TABLE atest
CREATE TABLE [dbo].[atest](
[id] [int] NULL,
[value] [varchar](50) NULL,
[X] [varchar](50) NULL
) ON [PRIMARY]
INSERT INTO atest (id, value, X)
VALUES (1, 'ONE', 'EXTRA STUFF'),
(2, 'TWO', 'OTHER'),
(3, 'THREE', 'NOT THIS')
DECLARE #X VARCHAR(100) = (SELECT TOP 1 X FROM atest)
SELECT [id], [value] + '-->' + #X FROM atest
This would result in:
1 ONE-->EXTRA STUFF
2 TWO-->EXTRA STUFF
3 THREE-->EXTRA STUFF
You could also make a temp table, or do self joins. I think there are some solutions here to get you what you want. Good luck! :)

Not directly, but you could consider selecting the values form Table1 into temp table and then using dynamic UPDATE statement to add the value form table specified by col3. Not elegant and have not tried on DB, but something like this might get you around problem
SELECT Col1,
Col2,
Col3
TopOfCol3Table = ''
INTO #TempTable1
FROM Table1
DECLARE #Sql VARCHAR(1024) = '
UPDATE #TempTable1
SET TopOfCol3Table = (SELECT TOP 1 Col FROM ' + Col3 ')'
EXECUTE sp_executesql #Sql

You can execute TSQL commands by calling the stored procedure sp_executesql that takes your TSQL command text as parameter.
Here's some documentation about it: sp_executesql (Transact-SQL)
What you do with the result is all part of your implementation.

Related

Temporary table using Transact sql

I'm beginner to T-SQL, I have this issue: I'd like to use a temporary table without creating it, so I wrote this stored procedure :
create PROCEDURE [dbo].[proc_Affaires_By_Client]
#clt_nom varchar(255) ,
#cmd_numero varchar(10),
#etap_cmd_libelle varchar(50),
#typ_cmd_libelle varchar(50)
AS
Begin
DECLARE #temp_tbl_proc TABLE (cmd_code_pk int NOT NULL,
clt_nom varchar(255) NOT NULL,
cmd_nom varchar(100) NOT NULL,
etap_cmd_libelle varchar(50) NULL,
DateAncienTS DateTime NULL,
DateTecentTS DateTime NULL,
TotalHeure numeric(3,2) not null,
TotalHeurePerid numeric(3,2) not null
);
INSERT INTO #temp_tbl_proc(cmd_code_pk, clt_nom, cmd_numero, cmd_nom, etap_cmd_libelle, typ_cmd_libelle, DateAncienTS, DateTecentTS, TotalHeure, TotalHeurePerid)
SELECT
ISNULL(cmd_code_pk, 1) AS cmd_code_pk, clt_nom, cmd_numero,
cmd_nom, etap_cmd_libelle, typ_cmd_libelle,
CONVERT(datetime, '01/01/1900', 103) AS DateAncienTS,
CONVERT(datetime, '01/01/1900', 103) AS DateTecentTS,
-1.00 AS TotalHeure, -1.00 AS TotalHeurePerid
FROM
OPENQUERY(SAB, 'SELECT c.cmd_code_pk, cl.clt_nom, c.cmd_numero, c.cmd_nom,et.etap_cmd_libelle,ty.typ_cmd_libelle FROM commande c,client cl,etape_commande et, type_commande ty where cl.clt_code_pk=c.cmd_clt_fk and c.cmd_etap_cmd_fk = et.etap_cmd_code_pk and c.cmd_typ_cmd_fk = ty.typ_cmd_code_pk' )
SELECT *
FROM #temp_tbl_proc
ORDER BY cmd_nom;
END
The problems are :
the temporary table will be created and added in the database
##query and #query are not recognized as a valid parameter
So how can I fix these problems?
From https://msdn.microsoft.com/en-us/library/ms188427(v=sql.110).aspx
OPENQUERY does not accept variables for its arguments.
So you have to craft a dynamic query, or in your cace, just move the query text into the OPENQUERY
OPENQUERY(SAB, 'Query text comes here')
To pass 'parameters', you can follow the instructions described here: https://support.microsoft.com/en-us/kb/314520
Essentially you have to craft a dynamic query and execute it as a dynamic query text.
You can use the OPENQUERY() a table in queries:
SELECT * FROM OPENQUERY(LinkedServer, 'QueryText') AS R;
Here are some rules to follow:
Add an alias to each returning columns in the QueryText (SQL Server can't handle anonimous columns),
Return only the necessary columns (to decrease the network traffic and the load of the remote and local servers)
You have to add an alias to the OPENQUERY expression in the FROM clause.
So with, a simple example:
DECLARE #localCache TABLE (id INT, col1 VARCHAR(MAX));
INSERT INTO #localCache (id, col1)
SELECT
id, col1
FROM
OPENQUERY(LinkedServer, '
SELECT X.id AS id, Y.col AS col1
FROM X INNER JOIN Y ON X.id = Y.x_id
') src
This could be tricky when you have to pass parameters to the remote query, since you have to create a dynamic query. Dynamic queries are executed in a different context, so the original SP's variables are not available.
DECLARE #myFilter NVARCHAR(32) = 'foo'
DECLARE #dymanicQuery NVARCHAR(MAX) = N'
INSERT INTO #localCache (id, col1)
SELECT
id, col1
FROM
OPENQUERY(LinkedServer, ''
SELECT X.id AS id, Y.col AS col1
FROM X INNER JOIN Y ON X.id = Y.x_id
WHERE Y.col2 = ''''' + #myFilter + '''''
'') src
';
DECLARE #remoteData TABLE (id INT, col1 VARCHAR(MAX));
INSERT INTO #remoteData (id, col1)
EXEC sp_executesql
#stmt = #dymanicQuery
Please note, that this could be dangerous and in this form it is open for sql injecions.
If you can do it, keep the data in sync in a permanent table (using SSIS for example) and use the synchronised data.

Ignore SQL Missing Columns During Execution Time

I am working on a tool (using c# winforms) which generates SQL scripts of data which are independent of identities but yet not violating constraints. While walking through all possibilities I got into below trouble. I need to insert data considering the fact a column (which allows null) may exists or not.
For example, a column as VAL2 exists in dev box, but may or may not exists in prod box.
CREATE TABLE TEMP ( COL1 VARCHAR(50) , VAL1 VARCHAR(50)) -- OPTIONAL/MAY EXISTS VAL2 VARCHAR(50)
IF EXISTS (SELECT TOP(1) COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TEMP' AND COLUMN_NAME = 'VAL2')
BEGIN
INSERT INTO TEMP (COL1,VAL1,VAL2) VALUES ('1','YES','NO')
INSERT INTO TEMP (COL1,VAL1,VAL2) VALUES ('2','NO','NO')
END
ELSE
BEGIN
INSERT INTO TEMP (COL1,VAL1) VALUES ('1','YES')
INSERT INTO TEMP (COL1,VAL1) VALUES ('2','NO')
END
GO
But this method fails miserably if that column is missing even though its should be flowing through else by syntax.
Note: I had for now made a work around but adding that column and dropping it at end if only created through current script. But the problem is the execution is through limited access grant which rules possibility of CREATE/DROP statement.This may be wrong, but that's the way it is for me.
If there is any alternate way preferably which doesn't mandates adding this column , please do guide me.
You'll have to use dynamic sql to accomplish that:
CREATE TABLE TEMP
(
COL1 VARCHAR(50) ,
VAL1 VARCHAR(50)
)
-- OPTIONAL/MAY EXISTS VAL2 VARCHAR(50)
IF EXISTS ( SELECT TOP ( 1 )
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEMP'
AND COLUMN_NAME = 'VAL2' )
BEGIN
DECLARE #sql NVARCHAR(MAX)
SELECT #sql = 'INSERT INTO TEMP (COL1,VAL1,VAL2) VALUES (''1'',''YES'',''NO'')
INSERT INTO TEMP (COL1,VAL1,VAL2) VALUES (''2'',''NO'',''NO'')'
EXEC sp_executesql #sql
END
ELSE
BEGIN
INSERT INTO TEMP
( COL1, VAL1 )
VALUES ( '1', 'YES' )
INSERT INTO TEMP
( COL1, VAL1 )
VALUES ( '2', 'NO' )
END

sp_MSforeachtable - parsing of dynamic sql

I recently found an issue whereby I wanted to use the sp_MSforeachtable stored proc to select all tables with the word Transcode in the table name, and to run some SQL on those tables. I managed to write some code which worked, but not perfectly - for those tables which I'd hoped it would gracefully skip over (i.e. those which did not have transcode in the name) it instead threw errors due to certain expected columns (which only exist in the transcode tables) not existing on those tables. The issue seems to be that all SQL is parsed when the stored proc is called, rather than parsing the SQL only when required (e.g. when a condition is met).
The following code works as expected:
exec sp_MSforeachtable '
print ''Table being tested: ?''
if exists (select 1 where ''?'' like ''%Transcode%'')
begin
print '' Do Something''
end
else
begin
print '' Ignored''
end
'
However, when I then try to add functionality, I get errors from code which would never be run; e.g.
exec sp_MSforeachtable '
print ''Table being tested: ?''
if exists (select 1 where ''?'' like ''%Transcode%'')
begin
print '' Do Something''
insert ? (col1, col2, col3)
select col1, col2, 1
from ?
where col3 = 0
end
else
begin
print '' Ignored''
end
'
This time I get the same output as the first one for those where the tablename contains the word Transcode, but for those where it doesn't instead of seeing Ignored, I see:
Msg 207, Level 16, State 1, Line 9
Invalid column name col3
I'm pretty sure this is down to the way the dynamic SQL is parsed, but it's undesirable behaviour. Has anyone come across this before / is there a simple workaround?
This is not urgent as in my case thanks to the columns not existing the errors had the same effect as the if statement anyway, and the valid lines were able to run successfully, but I'm keen to learn in case I need to do something similar soon where this behaviour would cause issues.
Thanks in advance,
JB
ps. code to replicate this behaviour's included below:
create table DemoTranscode1 (id bigint identity(1,1) primary key clustered, col1 nvarchar(10) not null, col2 nvarchar(10)not null, col3 bit not null)
go
create table DemoTable1 (id bigint identity(1,1) primary key clustered, col1 nvarchar(10) not null, col2 nvarchar(10)not null)
go
create table DemoTranscode2 (id bigint identity(1,1) primary key clustered, col1 nvarchar(10) not null, col2 nvarchar(10)not null, col3 bit not null)
go
create table DemoTranscode3 (id bigint identity(1,1) primary key clustered, col1 nvarchar(10) not null, col2 nvarchar(10)not null, col3 bit not null)
go
insert DemoTranscode1
select 'example1', 'demo', 0
union select 'example2', 'demo', 0
union select 'example3', 'demo', 0
union select 'example4', 'demo', 0
insert DemoTable1 select col1, col2 from DemoTranscode1
insert DemoTranscode2 select col1, col2, col3 from DemoTranscode1
insert DemoTranscode3 select col1, col2, col3 from DemoTranscode1
For one, I recommend staying away from undocumented and unsupported procedures like sp_MSForEachTable. They can be changed or even removed from SQL Server at any time, and this specific procedure may have the same symptoms reported by many against sp_MSForEachDb. (See some background here and here.)
Here is how I would do it:
DECLARE #sql NVARCHAR(MAX);
SELECT #sql = N'';
SELECT #sql = #sql + 'INSERT '
+ QUOTENAME(SCHEMA_NAME([schema_id]))
+ '.' + QUOTENAME(name) + ' (col1, col2, col3)
SELECT col1, col2, 1 FROM '
+ QUOTENAME(SCHEMA_NAME([schema_id]))
+ '.' + QUOTENAME(name)
+ ' WHERE col3 = 0;'
FROM sys.tables
WHERE name LIKE '%Transcode%';
PRINT #sql;
-- EXEC sp_executesql #sql;
The nice thing about this is it's easy to validate the output before executing.
You can use the #whereand parameter so you don't need to check in your code.
exec sp_MSforeachtable
#Command1 = 'print "?"',
#whereand = ' and o.name like ''%Transcode%'''
Update:
I'm pretty sure this is down to the way the dynamic SQL is parsed, but
it's undesirable behaviour. Has anyone come across this before
Sure. the code compiles before it is executed and the compiler checks the column names used in the insert statement against the table.
The issue is with the parser. Whether you use a sp_msforeachtable with some condition, still it will parse for each table. So, for other tables - throws error. You may use exec statement to avoid it as shown below -
exec sp_MSforeachtable '
print ''Table being tested: ?''
if exists (select 1 where ''?'' like ''%Transcode%'')
begin
print '' Do Something''
exec ( ''insert ? (col1, col2, col3) select col1, col2, 1 from ? where col3 = 0 '')
end
else
begin
print '' Ignored''
end
'

SQL: Cancel 'where' on null parameter

This may be obvious but I'm getting very confused.
I have an SQL query with a where clause (where in with a list of parameters). If all of these parameters are null, I need the SQL to ignore the where clause and retrieve all the records. Is this easy to do in SQL? I know one way around it is to just remove the where clause using code if the parameters are null.
You could try do something like this:
select *
from foo
where (#parameter1 is null AND #parameter2 is null)
OR (#parameter1 = 'value1'
AND
#parameter2 = 'value2')
Offcourse it needs a bit of tuning in your own query, but now you will check if the parameters are null or do your original where-clause.
The most performant way is to not include the WHERE clause at all if that's an option for you.
You often see tricks such as WHERE X=#X OR #X IS NULL used but these can lead to sub optimal plans and unnecessary table scans in the event you are passing a specific value for #X
Edit:
As this answer seems to have met with some unexpected scepticism...
create table #t
(
id varchar(5) primary key /*varchar to test LIKE without causing any casts*/
)
INSERT INTO #t
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM sys.all_columns
SET STATISTICS IO ON
/*Test the equals */
EXEC sp_executesql N'
SELECT *
FROM #t
WHERE (#id IS NULL OR id = #id)', N'#id varchar(5)', #id='1'
/*Is `LIKE` any better? */
EXEC sp_executesql N'
SELECT *
FROM #t
WHERE (#id IS NULL OR id LIKE #id)', N'#id varchar(5)', #id='1'
/*What should the plan look like? */
EXEC sp_executesql N'
SELECT *
FROM #t
WHERE (id = #id)', N'#id varchar(5)', #id='1'
DROP TABLE #t
if it's a stored procedure, either you do with dynamic SQL and do not append the where clause at all if parameters are null, or you still use an IF ELSE and write the query twice in the IF and in the else one with the where and one without, I agree with Martin that the where should be fully avoided if all records should be retrieved.
...
WHERE
(
col1 IS NULL
AND col2 IS NULL
AND col3 IS NULL
) OR
(
conditions...
);
i really think this will work
Where ((CASE WHEN #Parameter1 is null then 1 else 0 end) = 1 and
(CASE WHEN #Parameter2 is null then 1 else 0 end) = 1)
Have a look here handling-optional-parameters for an article fitting your requirements. The article compares various ways of doing optional parameters and discusses different versions of SQL Server as well as the performance of each.
I think what you are after is an individual IS NULL + OR per column, right?
WHERE (#col1 IS NULL OR col1 LIKE #col1)
AND (#col2 IS NULL OR col2 = #col2)

Insert default value when parameter is null

I have a table that has a column with a default value:
create table t (
value varchar(50) default ('something')
)
I'm using a stored procedure to insert values into this table:
create procedure t_insert (
#value varchar(50) = null
)
as
insert into t (value) values (#value)
The question is, how do I get it to use the default when #value is null? I tried:
insert into t (value) values ( isnull(#value, default) )
That obviously didn't work. Also tried a case statement, but that didn't fair well either. Any other suggestions? Am I going about this the wrong way?
Update: I'm trying to accomplish this without having to:
maintain the default value in multiple places, and
use multiple insert statements.
If this isn't possible, well I guess I'll just have to live with it. It just seems that something this should be attainable.
Note: my actual table has more than one column. I was just quickly writing an example.
Christophe,
The default value on a column is only applied if you don't specify the column in the INSERT statement.
Since you're explicitiy listing the column in your insert statement, and explicity setting it to NULL, that's overriding the default value for that column
What you need to do is "if a null is passed into your sproc then don't attempt to insert for that column".
This is a quick and nasty example of how to do that with some dynamic sql.
Create a table with some columns with default values...
CREATE TABLE myTable (
always VARCHAR(50),
value1 VARCHAR(50) DEFAULT ('defaultcol1'),
value2 VARCHAR(50) DEFAULT ('defaultcol2'),
value3 VARCHAR(50) DEFAULT ('defaultcol3')
)
Create a SPROC that dynamically builds and executes your insert statement based on input params
ALTER PROCEDURE t_insert (
#always VARCHAR(50),
#value1 VARCHAR(50) = NULL,
#value2 VARCHAR(50) = NULL,
#value3 VARCAHR(50) = NULL
)
AS
BEGIN
DECLARE #insertpart VARCHAR(500)
DECLARE #valuepart VARCHAR(500)
SET #insertpart = 'INSERT INTO myTable ('
SET #valuepart = 'VALUES ('
IF #value1 IS NOT NULL
BEGIN
SET #insertpart = #insertpart + 'value1,'
SET #valuepart = #valuepart + '''' + #value1 + ''', '
END
IF #value2 IS NOT NULL
BEGIN
SET #insertpart = #insertpart + 'value2,'
SET #valuepart = #valuepart + '''' + #value2 + ''', '
END
IF #value3 IS NOT NULL
BEGIN
SET #insertpart = #insertpart + 'value3,'
SET #valuepart = #valuepart + '''' + #value3 + ''', '
END
SET #insertpart = #insertpart + 'always) '
SET #valuepart = #valuepart + + '''' + #always + ''')'
--print #insertpart + #valuepart
EXEC (#insertpart + #valuepart)
END
The following 2 commands should give you an example of what you want as your outputs...
EXEC t_insert 'alwaysvalue'
SELECT * FROM myTable
EXEC t_insert 'alwaysvalue', 'val1'
SELECT * FROM myTable
EXEC t_insert 'alwaysvalue', 'val1', 'val2', 'val3'
SELECT * FROM myTable
I know this is a very convoluted way of doing what you need to do.
You could probably equally select the default value from the InformationSchema for the relevant columns but to be honest, I might consider just adding the default value to param at the top of the procedure
Try an if statement ...
if #value is null
insert into t (value) values (default)
else
insert into t (value) values (#value)
As far as I know, the default value is only inserted when you don't specify a value in the insert statement. So, for example, you'd need to do something like the following in a table with three fields (value2 being defaulted)
INSERT INTO t (value1, value3) VALUES ('value1', 'value3')
And then value2 would be defaulted. Maybe someone will chime in on how to accomplish this for a table with a single field.
Probably not the most performance friendly way, but you could create a scalar function that pulls from the information schema with the table and column name, and then call that using the isnull logic you tried earlier:
CREATE FUNCTION GetDefaultValue
(
#TableName VARCHAR(200),
#ColumnName VARCHAR(200)
)
RETURNS VARCHAR(200)
AS
BEGIN
-- you'd probably want to have different functions for different data types if
-- you go this route
RETURN (SELECT TOP 1 REPLACE(REPLACE(REPLACE(COLUMN_DEFAULT, '(', ''), ')', ''), '''', '')
FROM information_schema.columns
WHERE table_name = #TableName AND column_name = #ColumnName)
END
GO
And then call it like this:
INSERT INTO t (value) VALUES ( ISNULL(#value, SELECT dbo.GetDefaultValue('t', 'value') )
This is the best I can come up with. It prevents sql injection uses only one insert statement and can ge extended with more case statements.
CREATE PROCEDURE t_insert ( #value varchar(50) = null )
as
DECLARE #sQuery NVARCHAR (MAX);
SET #sQuery = N'
insert into __t (value) values ( '+
CASE WHEN #value IS NULL THEN ' default ' ELSE ' #value ' END +' );';
EXEC sp_executesql
#stmt = #sQuery,
#params = N'#value varchar(50)',
#value = #value;
GO
chrisofspades,
As far as I know that behavior is not compatible with the way the db engine works,
but there is a simple (i don't know if elegant, but performant) solution to achive your two objectives of DO NOT
maintain the default value in multiple places, and
use multiple insert statements.
The solution is to use two fields, one nullable for insert, and other one calculated to selections:
CREATE TABLE t (
insValue VARCHAR(50) NULL
, selValue AS ISNULL(insValue, 'something')
)
DECLARE #d VARCHAR(10)
INSERT INTO t (insValue) VALUES (#d) -- null
SELECT selValue FROM t
This method even let You centralize the management of business defaults in a parameter table, placing an ad hoc function to do this, vg changing:
selValue AS ISNULL(insValue, 'something')
for
selValue AS ISNULL(insValue, **getDef(t,1)**)
I hope this helps.
The best option by far is to create an INSTEAD OF INSERT trigger for your table, removing the default values from your table, and moving them into the trigger.
This will look like the following:
create trigger dbo.OnInsertIntoT
ON TablenameT
INSTEAD OF INSERT
AS
insert into TablenameT
select
IsNull(column1 ,<default_value>)
,IsNull(column2 ,<default_value>)
...
from inserted
This makes it work NO MATTER what code tries to insert NULLs into your table, avoids stored procedures, is completely transparent, and you only need to maintain your default values in one place, namely this trigger.
You can use default values for the parameters of stored procedures:
CREATE PROCEDURE MyTestProcedure ( #MyParam1 INT,
#MyParam2 VARCHAR(20) = ‘ABC’,
#MyParam3 INT = NULL)
AS
BEGIN
-- Procedure body here
END
If #MyParam2 is not supplied, it will have the 'ABC' value...
You can use the COALESCE function in MS SQL.
INSERT INTO t ( value ) VALUES( COALESCE(#value, 'something') )
Personally, I'm not crazy about this solution as it is a maintenance nightmare if you want to change the default value.
My preference would be Mitchel Sellers proposal, but that doesn't work in MS SQL. Can't speak to other SQL dbms.
Don't specify the column or value when inserting and the DEFAULT constaint's value will be substituted for the missing value.
I don't know how this would work in a single column table. I mean: it would, but it wouldn't be very useful.
Hope To help to -newbie as i am- Ones who uses Upsert statements in MSSQL.. (This code i used in my project on MSSQL 2008 R2 and works simply perfect..May be It's not Best Practise.. Execution time statistics shows execution time as 15 milliSeconds with insert statement)
Just set your column's "Default value or binding" field as what you decide to use as default value for your column and Also set the column as Not accept null values from design menu and create this stored Proc..
`USE [YourTable]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[YourTableName]
#Value smallint,
#Value1 bigint,
#Value2 varchar(50),
#Value3 varchar(20),
#Value4 varchar(20),
#Value5 date,
#Value6 varchar(50),
#Value7 tinyint,
#Value8 tinyint,
#Value9 varchar(20),
#Value10 varchar(20),
#Value11 varchar(250),
#Value12 tinyint,
#Value13 varbinary(max)
-- in my project #Value13 is a photo column which storing as byte array..
--And i planned to use a default photo when there is no photo passed
--to sp to store in db..
AS
--SET NOCOUNT ON
IF #Value = 0 BEGIN
INSERT INTO YourTableName (
[TableColumn1],
[TableColumn2],
[TableColumn3],
[TableColumn4],
[TableColumn5],
[TableColumn6],
[TableColumn7],
[TableColumn8],
[TableColumn9],
[TableColumn10],
[TableColumn11],
[TableColumn12],
[TableColumn13]
)
VALUES (
#Value1,
#Value2,
#Value3,
#Value4,
#Value5,
#Value6,
#Value7,
#Value8,
#Value9,
#Value10,
#Value11,
#Value12,
default
)
SELECT SCOPE_IDENTITY() As InsertedID
END
ELSE BEGIN
UPDATE YourTableName SET
[TableColumn1] = #Value1,
[TableColumn2] = #Value2,
[TableColumn3] = #Value3,
[TableColumn4] = #Value4,
[TableColumn5] = #Value5,
[TableColumn6] = #Value6,
[TableColumn7] = #Value7,
[TableColumn8] = #Value8,
[TableColumn9] = #Value9,
[TableColumn10] = #Value10,
[TableColumn11] = #Value11,
[TableColumn12] = #Value12,
[TableColumn13] = #Value13
WHERE [TableColumn] = #Value
END
GO`
With enough defaults on a table, you can simply say:
INSERT t DEFAULT VALUES
Note that this is quite an unlikely case, however.
I've only had to use it once in a production environment. We had two closely related tables, and needed to guarantee that neither table had the same UniqueID, so we had a separate table which just had an identity column, and the best way to insert into it was with the syntax above.
The most succinct solution I could come up with is to follow the insert with an update for the column with the default:
IF OBJECT_ID('tempdb..#mytest') IS NOT NULL DROP TABLE #mytest
CREATE TABLE #mytest(f1 INT DEFAULT(1), f2 INT)
INSERT INTO #mytest(f1,f2) VALUES (NULL,2)
INSERT INTO #mytest(f1,f2) VALUES (3,3)
UPDATE #mytest SET f1 = DEFAULT WHERE f1 IS NULL
SELECT * FROM #mytest
The pattern I generally use is to create the row without the columns that have default constraints, then update the columns to replace the default values with supplied values (if not null).
Assuming col1 is the primary key and col4 and col5 have a default contraint
-- create initial row with default values
insert table1 (col1, col2, col3)
values (#col1, #col2, #col3)
-- update default values, if supplied
update table1
set col4 = isnull(#col4, col4),
col5 = isnull(#col5, col5)
where col1 = #col1
If you want the actual values defaulted into the table ...
-- create initial row with default values
insert table1 (col1, col2, col3)
values (#col1, #col2, #col3)
-- create a container to hold the values actually inserted into the table
declare #inserted table (col4 datetime, col5 varchar(50))
-- update default values, if supplied
update table1
set col4 = isnull(#col4, col4),
col5 = isnull(#col5, col5)
output inserted.col4, inserted.col5 into #inserted (col4, col5)
where col1 = #col1
-- get the values defaulted into the table (optional)
select #col4 = col4, #col5 = col5 from #inserted
Cheers...
The easiest way to do this is to modify the table declaration to be
CREATE TABLE Demo
(
MyColumn VARCHAR(10) NOT NULL DEFAULT 'Me'
)
Now, in your stored procedure you can do something like.
CREATE PROCEDURE InsertDemo
#MyColumn VARCHAR(10) = null
AS
INSERT INTO Demo (MyColumn) VALUES(#MyColumn)
However, this method ONLY works if you can't have a null, otherwise, your stored procedure would have to use a different form of insert to trigger a default.
The questioner needs to learn the difference between an empty value provided and null.
Others have posted the right basic answer: A provided value, including a null, is something and therefore it's used. Default ONLY provides a value when none is provided. But the real problem here is lack of understanding of the value of null.
.