Related
How to delete records with a default value? I tried to delete using 'as default' and '= default' but this doesn't work. Is there a way for this?
My code:
delete from Address
where District = default
delete from Address
where District as default
Error:
Incorrect syntax near the keyword 'default'.
You can look up the default value for the column:
SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #SchemaName AND
TABLE_NAME = 'Address' AND
COLUMN_NAME = 'District'
And then incorporate this into a query. You can also do that directly, but it becomes a little tricky because the types might not match.
But, if distinct is a string, you can use:
delete from Address
where District = (select default_value
from information_schema.columns
where table_schema = #table_schema and
table_name = 'Address' and
column_name = 'District'
);
Important caveat: This deletes any row where the value matches the default value, even if that value were explicitly assigned to the column.
And, if the default value is NULL then slightly different comparisons are needed.
create table dbo.testabc
(
id int identity primary key clustered,
colA varchar(100) default('abc'),
colB int default(123456),
colC date default(getdate())
);
insert into dbo.testabc(colA, colB, colC)
values ('xyz', 123, '20200402'),
(default, 1, '20200220'),('efd', default, '20200320'),('bcd', 100, default);
go
declare #t table(colAdef sql_variant, colBdef sql_variant, colCdef sql_variant);
begin transaction
update top (1) dbo.testabc
set colA = default,
colB = default,
colC = default
output inserted.colA, inserted.colB, inserted.colC into #t(colAdef, colBdef, colCdef)
rollback transaction
select 'default values', *
from #t;
select *
from dbo.testabc as a
where exists(select * from #t as t where t.colAdef = a.colA)
or exists(select * from #t as t where t.colBdef = a.colB)
or exists(select * from #t as t where t.colCdef = a.colC)
go
--cleanup
drop table dbo.testabc;
go
I want to display value of other column if the value of my column is NULL or blank. Below is my table.
DECLARE #Tab TABLE(ID INT, suser VARCHAR(10), sgroup VARCHAR(10), sregion VARCHAR(10))
INSERT INTO #Tab VALUES(1,'Test',NULL,NULL),(2,'','Group',NULL),(3,NULL,NULL,'Region'),(4,NULL,NULL,NULL)
SELECT * from #Tab
My Query:
SELECT ID
,Case WHEN suser IS NULL OR suser = ''
THEN sgroup
WHEN sgroup IS NULL OR sgroup = ''
THEN sregion
ELSE NULL
END AS col
from #Tab
I want oupput as:-
DECLARE #Tab1 TABLE(ID INT, col VARCHAR(10))
INSERT INTO #Tab1 VALUES(1,'Test'),(2,'Group'),(3,'Region'),(4,NULL)
SELECT * from #Tab1
Thanks
Blank and NULL are not the same. If you want to treat '' and NULL as the same value, one method would be to use NULLIF:
ISNULL(NULLIF(YourFirstColumn,''),YourOtherColumn)
Ideally, however, if either could be stored in your data but they should be treated as the same, don't allow one of them. Personally, I would update all the values of the column to NULL where they have a value of '' and then add a constraint that doesn't allow the value ''. Something like:
UPDATE YourTable
SET YourColumn = NULL
WHERE YourColumn = '';
ALTER TABLE YourTable ADD CONSTRAINT YourColumn_NotBlank CHECK (YourColumn IS NULL OR YourColumn <> '');
use COALESCE function it will return 1st non null value
SELECT ID ,COALESCE(suser , sgroup, sregion)
col
from #Tab
Consider the table in SQL Server 2012
789-0000000
The above number will be consider as a string in SQL Server 2012, but whenever I update the record I need increment to 1.
For example:
When I update the record 1 it should increment to 789-0000001
When I update the record 2 it should increment to 789-0000002
Finally increment should done only 789-0000000
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.YourTable
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS '789-' + RIGHT('000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into dbo.YourTable without specifying values for ID or CompanyID:
INSERT INTO dbo.YourTable(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will automatically and safely increase your ID value, and CompanyID will contain values like 789-0000001, 789-0000002,...... and so on - automatically, safely, reliably, no duplicates.
DECLARE #base int = 0
UPDATE TableX
SET
TableX.Value = 'Prefix' + RIGHT('0000000' + CAST(#base AS nvarchar),7),
#base = #base + 1
FROM
TableX
you can split the string
e.g.:
SELECT Item
FROM dbo.SplitString('Apple,Mango,Banana,Guava', ',')
then cast it
e.g.:
SELECT CAST(YourVarcharCol AS INT) FROM Table
then manually increment it
e.g.:
DECLARE max_id INT
SET #max_id = (SELECT MAX(id) FROM source_table)
DECLARE cursor_name CURSOR FOR
SELECT columns, to, copy
FROM source_table
OPEN cursor_name
FETCH NEXT FROM cursor_name
INTO #columns, #to, #cop
at update
e.g.:
declare #i int = SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices
update prices
set interfaceID = #i , #i = #i + 1
where interfaceID is null
you can understand how complicate this is and why
the solution using a constant to store that prefix is right one.
Declare #str varchar(max) = '789-0000000'
Select
SUBSTRING ( #str ,0 ,CHARINDEX ( '-' ,#str ))
+'-'
+
(SUBSTRING ( #str ,(CHARINDEX ( '-' ,#str)+1) ,(7-LEN(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int))
)
)+
CAST(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int)+1 as varchar))
When #str='789-0001947'
Output #str= 789-0001948
You can write a update trigger on the table with above logic.
I have two tables named Retail and Activity and the data is as shown below:
Retail Table
Activity Table
My main concern is about Ok and Fault column of the table Retail, as you can see it contains comma separated value of ActivityId.
What i want is, if the Ok column has ActivityId the corresponding column will have Yes, if the Fault column has ActivityId then it should be marked as No
Note I have only four columns that is fixed, it means i have to check that either four of the columns has its value in Ok or Fault, if yes then only i have to print yes or no, otherwise null.
Desired result should be like :
If the value is in Ok then yes other wise No.
I guessing you want to store 'yes' or 'No' in some column. Below is the query to update that column :
UPDATE RetailTable
SET <Result_Column>=
CASE
WHEN Ok IS NOT NULL THEN 'Yes'
WHEN Fault IS NOT NULL THEN 'No'
END
You can use below code as staring point:
DECLARE #Retail TABLE
(
PhoneAuditID INT,
HandsetQuoteID INT,
Ok VARCHAR(50)
)
INSERT INTO #Retail VALUES (1, 1009228, '4,22,5')
INSERT INTO #Retail VALUES (2, 1009229, '1')
DECLARE #Activity TABLE
(
ID INT,
Activity VARCHAR(50)
)
INSERT INTO #Activity VALUES (1, 'BatteryOK?'), (4, 'PhonePowersUp?'), (22,'SomeOtherQuestion?'), (5,'LCD works OK?')
SELECT R.[PhoneAuditID], R.[HandsetQuoteID], A.[Activity], [Ok] = CASE WHEN A.[ID] IS NOT NULL THEN 'Yes' END
FROM #Retail R
CROSS APPLY dbo.Split(R.Ok, ',') S
LEFT JOIN #Activity A ON S.[items] = A.[ID]
I have used Split function provided here:
separate comma separated values and store in table in sql server
Try following query. i have used pivot to show row as columns. I have also used split function to split id values which you can find easily on net:
CREATE TABLE PhoneAudit
(
PhoneAuditRetailID INT,
HandsetQuoteID INT,
Ok VARCHAR(50),
Fault VARCHAR(50)
)
INSERT INTO PhoneAudit VALUES (1,10090,'1,2','3')
CREATE TABLE ActivityT
(
ID INT,
Activity VARCHAR(100)
)
INSERT INTO ActivityT VALUES (1,'Battery')
INSERT INTO ActivityT VALUES (2,'HasCharger')
INSERT INTO ActivityT VALUES (3,'HasMemoryCard')
INSERT INTO ActivityT VALUES (4,'Test')
DECLARE #SQL AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','') + QUOTENAME(Activity) FROM (SELECT DISTINCT Activity FROM ActivityT) AS Activities
SET #SQL = 'SELECT PhoneAuditRetailID, HandsetQuoteID,
' + #ColumnName + '
FROM
(SELECT
t1.PhoneAuditRetailID,
t1.HandsetQuoteID,
TEMPOK.*
FROM
PhoneAudit t1
CROSS APPLY
(
SELECT
Activity,
(CASE WHEN ID IN (SELECT * FROM dbo.SplitIDs(t1.Ok,'',''))
THEN ''YES''
ELSE ''NO''
END) AS VALUE
FROM
ActivityT t2
) AS TEMPOK) AS t3
PIVOT
(
MIN(VALUE)
FOR Activity IN ('+ #ColumnName + ')
) AS PivotTable;'
EXEC sp_executesql #SQL
DROP TABLE PhoneAudit
DROP TABLE ActivityT
There are several ways to do this. If you are looking for a purely declarative approach, you could use a recursive CTE. The following example of this is presented as a generic solution with test data which should be adaptable to your needs:
Declare #Delimiter As Varchar(2)
Set #Delimiter = ','
Declare #Strings As Table
(
String Varchar(50)
)
Insert Into #Strings
Values
('12,345,6,78,9'),
(Null),
(''),
('123')
;With String_Columns As
(
Select
String,
Case
When String Is Null Then ''
When CharIndex(#Delimiter,String,0) = 0 Then ''
When Len(String) = 0 Then ''
Else Left(String,CharIndex(#Delimiter,String,0)-1)
End As String_Column,
Case
When String Is Null Then ''
When CharIndex(#Delimiter,String,0) = 0 Then ''
When Len(String) = 0 Then ''
When Len(Left(String,CharIndex(#Delimiter,String,0)-1)) = 0 Then ''
Else Right(String,Len(String)-Len(Left(String,CharIndex(#Delimiter,String,0)-1))-1)
End As Remainder,
1 As String_Column_Number
From
#Strings
Union All
Select
String,
Case
When CharIndex(#Delimiter,Remainder,0) = 0 Then Remainder
Else Left(Remainder,CharIndex(#Delimiter,Remainder,0)-1)
End As Remainder,
Case
When CharIndex(#Delimiter,Remainder,0) = 0 Then ''
When Len(Left(Remainder,CharIndex(#Delimiter,Remainder,0)-1)) = 0 Then ''
Else Right(Remainder,Len(Remainder)-Len(Left(Remainder,CharIndex(#Delimiter,Remainder,0)-1))-1)
End As Remainder,
String_Column_Number + 1
From
String_Columns
Where
(Remainder Is Not Null And Len(Remainder) > 1)
)
Select
String,
String_Column,
String_Column_Number
From
String_Columns
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.
.