Alter column, add default constraint - sql-server

I have a table and one of the columns is "Date" of type datetime. We decided to add a default constraint to that column
Alter table TableName
alter column dbo.TableName.Date default getutcdate()
but this gives me error:
Incorrect syntax near '.'
Does anyone see anything obviously wrong here, which I am missing (other than having a better name for the column)

Try this
alter table TableName
add constraint df_ConstraintNAme
default getutcdate() for [Date]
example
create table bla (id int)
alter table bla add constraint dt_bla default 1 for id
insert bla default values
select * from bla
also make sure you name the default constraint..it will be a pain in the neck to drop it later because it will have one of those crazy system generated names...see also How To Name Default Constraints And How To Drop Default Constraint Without A Name In SQL Server

you can wrap reserved words in square brackets to avoid these kinds of errors:
dbo.TableName.[Date]

Actually you have to Do Like below Example, which will help to Solve the Issue...
drop table ABC_table
create table ABC_table
(
names varchar(20),
age int
)
ALTER TABLE ABC_table
ADD CONSTRAINT MyConstraintName
DEFAULT 'This is not NULL' FOR names
insert into ABC(age) values(10)
select * from ABC

I use the stored procedure below to update the defaults on a column.
It automatically removes any prior defaults on the column, before adding the new default.
Examples of usage:
-- Update default to be a date.
exec [dbo].[AlterDefaultForColumn] '[dbo].[TableName]','Column','getdate()';
-- Update default to be a number.
exec [dbo].[AlterDefaultForColumn] '[dbo].[TableName]','Column,'6';
-- Update default to be a string. Note extra quotes, as this is not a function.
exec [dbo].[AlterDefaultForColumn] '[dbo].[TableName]','Column','''MyString''';
Stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Sample function calls:
--exec [dbo].[AlterDefaultForColumn] '[dbo].[TableName]','ColumnName','getdate()';
--exec [dbol].[AlterDefaultForColumn] '[dbo].[TableName]','Column,'6';
--exec [dbo].[AlterDefaultForColumn] '[dbo].[TableName]','Column','''MyString''';
create PROCEDURE [dbo].[ColumnDefaultUpdate]
(
-- Table name, including schema, e.g. '[dbo].[TableName]'
#TABLE_NAME VARCHAR(100),
-- Column name, e.g. 'ColumnName'.
#COLUMN_NAME VARCHAR(100),
-- New default, e.g. '''MyDefault''' or 'getdate()'
-- Note that if you want to set it to a string constant, the contents
-- must be surrounded by extra quotes, e.g. '''MyConstant''' not 'MyConstant'
#NEW_DEFAULT VARCHAR(100)
)
AS
BEGIN
-- Trim angle brackets so things work even if they are included.
set #COLUMN_NAME = REPLACE(#COLUMN_NAME, '[', '')
set #COLUMN_NAME = REPLACE(#COLUMN_NAME, ']', '')
print 'Table name: ' + #TABLE_NAME;
print 'Column name: ' + #COLUMN_NAME;
DECLARE #ObjectName NVARCHAR(100)
SELECT #ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID(#TABLE_NAME) AND [name] = #COLUMN_NAME;
IF #ObjectName <> ''
begin
print 'Removed default: ' + #ObjectName;
--print('ALTER TABLE ' + #TABLE_NAME + ' DROP CONSTRAINT ' + #ObjectName)
EXEC('ALTER TABLE ' + #TABLE_NAME + ' DROP CONSTRAINT ' + #ObjectName)
end
EXEC('ALTER TABLE ' + #TABLE_NAME + ' ADD DEFAULT (' + #NEW_DEFAULT + ') FOR ' + #COLUMN_NAME)
--print('ALTER TABLE ' + #TABLE_NAME + ' ADD DEFAULT (' + #NEW_DEFAULT + ') FOR ' + #COLUMN_NAME)
print 'Added default of: ' + #NEW_DEFAULT;
END
Errors this stored procedure eliminates
If you attempt to add a default to a column when one already exists, you will get the following error (something you will never see if using this stored proc):
-- Using the stored procedure eliminates this error:
Msg 1781, Level 16, State 1, Line 1
Column already has a DEFAULT bound to it.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.

I confirm like the comment from JohnH, never use column types in the your object names!
It's confusing. And use brackets if possible.
Try this:
ALTER TABLE [TableName]
ADD DEFAULT (getutcdate()) FOR [Date];

You're specifying the table name twice. The ALTER TABLE part names the table.
Try:
Alter table TableName
alter column [Date] default getutcdate()

alter table TableName
drop constraint DF_TableName_WhenEntered
alter table TableName
add constraint DF_TableName_WhenEntered
default getutcdate() for WhenEntered

Related

TRUNCATE multiple tables SQL Server 2014

I want to truncate multiple tables. I know that it isn't possible in the same way that DELETE will delete the rows from multiple tables.
In this question truncate multi tables IndoKnight provides the OP-designated best answer. I want to try that. However, I get a syntax error at:
TRUNCATE TABLE #tableName
To troubleshoot I tried printing the variables because when I first tried using TRUNCATE TABLE I needed to include the database name and schema (e.g. NuggetDemoDB.dbo.tablename) to get it to work. I CAN print the variable #tableList. But I CANNOT print #tableName.
DECLARE #delimiter CHAR(1),
#tableList VARCHAR(MAX),
#tableName VARCHAR(20),
#currLen INT
SET #delimiter = ','
SET #tableList = 'Employees,Products,Sales'
--PRINT #tableList
WHILE LEN(#tableList) > 0
BEGIN
SELECT #currLen =
(
CASE charindex( #delimiter, #tableList )
WHEN 0 THEN len( #tableList )
ELSE ( charindex( #delimiter, #tableList ) -1 )
END
)
SET #tableName = SUBSTRING (#tableList,1,#currLen )
--PRINT #tableName
TRUNCATE TABLE #tableName
SELECT tableList =
(
CASE ( len( #tableList ) - #currLen )
WHEN 0 THEN ''
ELSE right( #tableList, len( #tableList ) - #currLen - 1 )
END
)
END
Edit: Fixed the table list to remove the extra "Sales" from the list of tables and added "Employees".
Even thought Sales is listed twice... No harm
Declare #TableList varchar(max)
SET #tableList = 'Sales,Products,Sales'
Set #tableList = 'Truncate Table '+replace(#tablelist,',',';Truncate Table ')+';'
Print #TableList
--Exec(#tablelist) --<< If you are TRULY comfortable with the results
Returns
Truncate Table Sales;Truncate Table Products;Truncate Table Sales
First and foremost, you may want to consider spending a little energy to come up with a SQL implementation for splitting a string into rows, e.g. Split, List, etc. This will prove to be helpful not only for this exercise, but for many others. Then this post is not about how to turn a comma separated list into rows and we can then concentrate on the dynamic SQL needed in order to do what is needed.
Example
The below example assumes that you have a function named List to take care of transposing the comma separated list into rows.
declare
#TableList varchar(max) = 'Sales, Products, Sales';
declare
#Sql varchar(max) = (
select distinct 'truncate table ' + name + ';'
from List(#TableList)
for xml path(''));
exec (#Sql);
One last thing about truncate of delete
Truncate will not work if you are truncating data where there is a foreign key relationship to another table.
You will get something like the below error.
Msg 4712, Level 16, State 1, Line 19
Cannot truncate table 'Something' because it is being referenced by a FOREIGN KEY constraint.
Below is an example that uses a table variable instead of delimited list. If the source of your table list is already in a table, you could tweak this script to use that as the source instead. Note that the extra Sales table is redundant (gleaned from the script your question) and can be removed. The table names can be database and/or schema qualified if desired.
DECLARE #tableList TABLE(TableName nvarchar(393));
DECLARE #TruncateTableBatch nvarchar(MAX);
INSERT INTO #tableList VALUES
(N'Sales')
, (N'Products')
, (N'Sales');
SET #TruncateTableBatch = (SELECT N'TRUNCATE TABLE ' + TableName + N'
'
FROM #tableList
FOR XML PATH(''), TYPE).value('.', 'nvarchar(MAX)');
--PRINT #SQL;
EXECUTE(#TruncateTableBatch);
What about something like:
exec sp_msforeachtable
#command1 ='truncate table ?'
,#whereand = ' and object_id In (select object_id from sys.objects where name in ("sales", "products")'
Have not tested it yet. But it might give a useful hint.

Removing Identity_Insert from a Temp Table that is Generated Dynamically

I've got a Stored Procedure that I want to audit all the changes it makes to many tables. This bit of code repeated down the SP but with different table names. Once that piece of script is finish I then copy the contents of the temp table to my audit table which works well.
I have a problem with one table which bring back this message: An explicit value for the identity column in table '#MyTempTable' can only be specified when a column list is used and IDENTITY_INSERT is ON.
I'm lazy, I don't want to specify all the column names. Is there a way to remove the identity from the temp table after I created it?
--Create Temp Audit Table
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL drop table #MyTempTable;
select top 0 * into #MyTempTable from TabletoAudit
--Do changes and record into TempTable
UPDATE TabletoAudit
SET
series_nm = #newseries,
UPDATED_DT = GetDate()
OUTPUT deleted.* INTO #MyTempTable
WHERE
mach_type_cd = #mtype
AND
brand_id = #brand
AND
series_nm = #oldseries
--Copy Contents from Temp table to Audit Table
If the identity column is the first column (usually it is) then you can also:
assuming data type INT, column name originalid
SELECT top 0 CONVERT(INT,0)myid,* into #MyTempTable from TabletoAudit
ALTER TABLE #MyTempTable DROP COLUMN originalid
EXEC tempdb.sys.sp_rename N'#MyTempTable.myid', N'originalid', N'COLUMN'
I spent over a day researching into this but now finally found a solution. Simply when I create it, create it without the Identity in the first place. I did this by creating a dynamic script to create a temp table based on another and don't add identity.
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..##MyTempTable') IS NOT NULL drop table ##INSERTED7;
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX);
DECLARE #CreateSQL NVARCHAR(MAX);
SET #sql = N'SELECT * FROM TabletoAudit;';
SELECT #CreateSQL = 'CREATE TABLE ##MyTempTable(';
SELECT
#CreateSQL = #CreateSQL + CASE column_ordinal
WHEN 1 THEN '' ELSE ',' END
+ name + ' ' + system_type_name + CASE is_nullable
WHEN 0 THEN ' not null' ELSE '' END
FROM
sys.dm_exec_describe_first_result_set (#sql, NULL, 0) AS f
ORDER BY column_ordinal;
SELECT #CreateSQL = #CreateSQL + ');';
EXEC sp_executesql #CreateSQL;
SET NOCOUNT OFF;
I also changed the Temp Table to a Global Temp Table for it to work.

Add a column, with a derived column name, to an existing table in SQL Server 2014

DECLARE
#countFlag INT,
#maxNum INT = 5,
#addingName NVARCHAR(6)
SET #countFlag = 1
WHILE (#countFlag <= #maxNum)
BEGIN
SET #addingName = 'name' + CAST(#countFlag AS NVARCHAR(2))
ALTER TABLE TableName
ADD
#addingName NVARCHAR(30)
SET #countFlag = #countFlag + 1
END
========================================================
This is called at the beginning of a set of procedures. #maxNum is actually passed in based on a question to the operator and changes the 'shape' of an existing db to include more columns. I would like to have the resulting column names be something like "name1" "name2" etc. but I am getting an "Incorrect syntax near '#addingName'" after the ADD statement when I execute it. What am I doing wrong here?
You cannot do it in that way, you should compose the query dynamically and execute it with Exec:
DECLARE #sqlCommand varchar(200)
SET #sqlCommand = 'ALTER TABLE TableName ADD ' + #addingName + ' NVARCHAR(30) '
EXEC (#sqlCommand)

"." char throws error in sql-server

This shouldn't be a very hard to solve problem, but I'm out pages on google to search for the solution.
I have a database with users that have their names like 'firstname.lastname'.
Example : john.smith , b.obama , v.putin and so on.
I try to add these users some roles within a SP
This is my SP :
ALTER PROCEDURE [dbo].[sp_adaugaUserInRol]
-- Add the parameters for the stored procedure here
#Rol varchar(50),
#User varchar(32)
AS
BEGIN
declare #sRol varchar(50),
#sUser varchar(32);
set #sUser = LTRIM(RTRIM(#User))
set #sRol = LTRIM(RTRIM(#Rol))
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
print(' ALTER ROLE ' + #sRol + ' ADD MEMBER ' +#User )
END
If I use a string for user like 'john' , 'obama' it works, but if I use it as 'john.smith' or 'b.obama' I get the error Incorrect syntax near '.'. , which is very logical as SQL thinks john is a table and smith is a column ( my guess ).
How can I tell SQL that john.smith is a string?
put it in square brackets:
[john.smith]
print(' ALTER ROLE [' + #sRol + '] ADD MEMBER [' +#User + ']' )

Updating nullability of columns in SQL 2008

I have a very wide table, containing lots and lots of bit fields. These bit fields were originally set up as nullable. Now we've just made a decision that it doesn't make sense to have them nullable; the value is either Yes or No, default No. In other words, the schema should change from:
create table MyTable(
ID bigint not null,
Name varchar(100) not null,
BitField1 bit null,
BitField2 bit null,
...
BitFieldN bit null
)
to
create table MyTable(
ID bigint not null,
Name varchar(100) not null,
BitField1 bit not null,
BitField2 bit not null,
...
BitFieldN bit not null
)
alter table MyTable add constraint DF_BitField1 default 0 for BitField1
alter table MyTable add constraint DF_BitField2 default 0 for BitField2
alter table MyTable add constraint DF_BitField3 default 0 for BitField3
So I've just gone in through the SQL Management Studio, updating all these fields to non-nullable, default value 0. And guess what - when I try to update it, SQL Mgmt studio internally recreates the table and then tries to reinsert all the data into the new table... including the null values! Which of course generates an error, because it's explicitly trying to insert a null value into a non-nullable column. Aaargh!
Obviously I could run N update statements of the form:
update MyTable set BitField1 = 0 where BitField1 is null
update MyTable set BitField2 = 0 where BitField2 is null
but as I said before, there are n fields out there, and what's more, this change has to propagate out to several identical databases. Very painful to implement manually.
Is there any way to make the table modification just ignore the null values and allow the default rule to kick in when you attempt to insert a null value?
If you're absolutely sure you want to do this for all the bit columns on the table, you can use a cursor to iterate over those columns and build the script dynamically. This is similar to Alexander's solution, except that it works if the columns aren't numbered 1..n (which I doubt -- I'm guessing those were probably simplified for illustration purposes).
DECLARE #colName sysname;
DECLARE #sql nvarchar(max);
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable' AND DATA_TYPE = 'bit' AND IS_NULLABLE = 'YES';
OPEN cur;
FETCH NEXT FROM cur INTO #colName;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'UPDATE [MyTable] SET ' + QUOTENAME(#colName)
+ N' = 0 WHERE ' + QUOTENAME(#colName) + N' IS NULL;'
+ N'ALTER TABLE [MyTable] ALTER COLUMN ' + QUOTENAME(#colName)
+ N' bit NOT NULL;'
+ N'ALTER TABLE [MyTable] ADD CONSTRAINT ' + QUOTENAME('DF_' + #colName)
+ N' DEFAULT(0) FOR ' + QUOTENAME(#colName) + N';';
EXEC (#sql); -- Replace with PRINT #sql; if you want to test first.
FETCH NEXT FROM cur INTO #colName;
END
CLOSE cur;
DEALLOCATE cur;
I think after all I'm just going to go with the N update statements.
It's a once-off job to write the script, which is mostly copy-and-paste, and then I can run that script on all applicable databases.
Still, I'd be interested to know if there is another more efficient way of doing this...
DECLARE #command VARCHAR(8000)
DECLARE #index int
SET #index=0
WHILE #index<=N DO BEGIN
SET #command=#command+'update MyTable SET BitField'+cast(#index as varchar(3))+' = 0 WHERE BitField'+cast(#index as varchar(3))+' IS NULL'
EXEC(#command)
SET #index=#index+1
END
and so on...

Resources