I've created a column called "Identified" and I've assigned a default value of "1". Now I realized that I would like to delete that column. But when I try I get the following error:
Msg 5074, Level 16, State 1, Line 5
The object 'DF__orders__Identifi__403A8C7D' is dependent on column 'Identified'.
Msg 4922, Level 16, State 9, Line 5
ALTER TABLE DROP COLUMN Identified failed because one or more objects access this column.
Here is the code used:
ALTER TABLE BikeStores.sales.orders
DROP COLUMN Identified;
I've also tried:
ALTER TABLE BikeStores.sales.orders
DROP Identified;
But in this case the error get is:
Msg 3728, Level 16, State 1, Line 5
'Identified' is not a constraint.
Msg 3727, Level 16, State 0, Line 5
Could not drop constraint. See previous errors.
Any tip on how to fix this error? Thanks in advance
The column cannot be dropped because the default constraint is dependant on the column existing. Drop the default constraint first.
If the version of SQL server you are working with is 2016 or before you can use the simple query:
ALTER TABLE BikeStores.sales.orders ALTER COLUMN Identified DROP DEFAULT;
From 2017 onwards you will need to explicitly use the default constraints name
ALTER TABLE BikeStores.sales.orders DROP CONSTRAINT DF__orders__Identifi__403A8C7D;
If you do not know the name of the default (due to it being auto named on creation) the following script will identify and remove the default.
declare #schema_name nvarchar(256)
declare #table_name nvarchar(256)
declare #col_name nvarchar(256)
declare #Command nvarchar(1000)
set #schema_name = N'sales'
set #table_name = N'orders'
set #col_name = N'Identitified'
select #Command = 'ALTER TABLE ' + #schema_name + '.[' + #table_name + '] DROP CONSTRAINT ' + d.name
from sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id
where t.name = #table_name
and t.schema_id = schema_id(#schema_name)
and c.name = #col_name
EXEC sp_executesql #Command
(credit to this question for the last part ) How to drop SQL default constraint without knowing its name?
You will then be able to drop your column
Related
This question already has answers here:
How to use a variable for the database name in T-SQL?
(4 answers)
Closed 2 years ago.
I have a problem with assigning a database name to a variable. When I do this, I get a message that there is no such database.
What am I doing wrong that this script doesn't work?
DECLARE #db_name varchar(10)
SET #db_name = 'xxx'
ALTER TABLE [#db_name].[dbo].[Table_Name]
DROP CONSTRAINT [Constraint_Name]
GO
ALTER TABLE [#db_name].[dbo].[Table_Name] WITH CHECK
ADD CONSTRAINT [Constraint_Name] CHECK (QUERY)
GO
ALTER TABLE [#db_name].[dbo].[Table_Name] CHECK CONSTRAINT [Constraint_Name]
GO
I'm getting this error message:
Msg 2702, Level 16, State 2, Line 5
Database '#db_name' does not exist.
Msg 2702, Level 16, State 2, Line 8
Database '#db_name' does not exist.
Msg 2702, Level 16, State 2, Line 11
Database '#db_name' does not exist.
let's say for example that you have a table created like this:
create table xxx(id int
CONSTRAINT AK_TransactionID UNIQUE(id))
Then you will need to cerate two variables(one for the object name and one for the query to be executed...):
DECLARE #db_name varchar(10) ;
DECLARE #query nvarchar(500) ;
Set them to the values you need:
SET #db_name = 'xxx';
set #query = 'ALTER TABLE ['+ #db_name +' ] DROP CONSTRAINT [AK_TransactionID]';
And then execute the query:
EXEC sp_executesql #query;
Here is a demo
A query - meaning all text until each GO command - is compiled before it is run.
Database names inside queries have to be be known at compile time, because the database + any table or column you specify are inspected by the query compiler to see if they are valid.
This means that Database names + Table names + Column names all cannot come from #-variables, because at compile time variables don't yet exist and have no value.
The fix is to use dynamic SQL:
DECLARE #db_name varchar(10) = 'xxx'
DECLARE #sql varchar(1000) = 'ALTER TABLE [' + #db_name + '].[dbo].[Table_Name] DROP CONSTRAINT [Constraint_Name]'
EXEC (#sql)
Unfortunately in SQL Server, you cannot pass schema, database, table or column names as a parameter - if you want to do this, you must use dynamic SQL. You could do the below to achieve this:
DECLARE #db_name VARCHAR(MAX)
DECLARE #SQL VARCHAR(MAX)
SET #db_name = [xxx]
SET #SQL = 'ALTER TABLE' + #db_name+ '.[dbo].[Table_Name] DROP CONSTRAINT [Constraint_Name]'
EXEC (#SQL)
SET #SQL = 'ALTER TABLE' + #db_name + '.[dbo].[Table_Name] WITH CHECK ADD CONSTRAINT [Constraint_Name] CHECK (QUERY)'
EXEC (#SQL)
SET #SQL = 'ALTER TABLE' + #db_name + '.[dbo].[Table_Name] CHECK CONSTRAINT [Constraint_Name]'
EXEC (#SQL)
I have to change all the columns in a database in all the tables (SQL Server) that are Date and convert them to DateTime.
How do I accomplish that? Is it a command?
I think this can help you :
Execute the script you will see the update list in the messages tab.
DECLARE #SQLString VARCHAR(MAX)=''
SELECT #SQLString = #SQLString +CHAR(13)+'ALTER TABLE '+T.TABLE_SCHEMA+'.'+T.TABLE_NAME+' ALTER COLUMN '+C.COLUMN_NAME+' DATETIME'
FROM INFORMATION_SCHEMA.TABLES T
INNER JOIN INFORMATION_SCHEMA.COLUMNS C ON T.TABLE_SCHEMA=C.TABLE_SCHEMA
AND T.TABLE_NAME=C.TABLE_NAME
WHERE C.DATA_TYPE='date'
AND T.TABLE_TYPE='BASE TABLE'
PRINT(#SQLString)
you can use this query to get collection of alter queries for your columns which are date type.
SELECT
CONCAT('alter table ', TABLE_SCHEMA, '.', TABLE_NAME, ' ALTER COLUMN ', COLUMN_NAME, ' DATETIME;')
FROM INFORMATION_SCHEMA.COLUMNS
Where DATA_TYPE = 'date' and TABLE_SCHEMA not in ('information_schema', 'sys');
then by executing generated results your table columns will be converted to DateTime
The command for altering a column, which must be called to change a datatype, is --> ALTER COLUMN. The ALTER COLUMN command can only be called from within the context of an ALTER TABLE command. You are lucky because the datatype you want to convert to is conversion compatible and only widens the column. If you attempt to convert to a incompatible datatype or a datatype that requires less storage then you could not use the simple command below.
ALTER TABLE YourTableName
ALTER COLUMN YouDateField DATETIME
Generate dynamic statement using sys.columns and sys.types and execute generated statement.
This statement also checks for nullability of each column.
ALTER TABLE ... ALTER COLUMN is not always a working solution. In some cases you'll probably need to drop the table and recreate it, or add new column, then copy the values for old column to the new one, and then drop the original column.
When you alter a column, consider at least the following:
the previous data type must be implicitly convertible to the new data type
new type cannot be timestamp.
ANSI_NULL defaults are always on for ALTER COLUMN; if not specified, the column is nullable.
T-SQL:
DECLARE
#stm nvarchar(max),
#err int
SELECT #stm = (
SELECT CONCAT(
'ALTER TABLE ', OBJECT_NAME(c.OBJECT_ID),
' ALTER COLUMN ',
c.name,
' datetime',
CASE
WHEN c.is_nullable = 1 THEN ' NULL '
ELSE ' NOT NULL '
END,
'; '
)
FROM sys.columns AS c
JOIN sys.types AS t ON c.user_type_id = t.user_type_id
WHERE t.name = 'date'
ORDER BY c.OBJECT_ID
FOR XML PATH('')
)
PRINT #stm
EXEC #err = sp_executesql #stm
IF #err = 0
PRINT 'OK'
ELSE
PRINT 'Error'
I have around 50+ table in my database now what I want is drop all the tables in database except few.
now what I know is sys.tables is a table that list all tables so initially I ran a query like this
delete from sys.tables where name like '%DynamicSurgery' (or any other condition)
thinking that it might work. But as I expected it throws an error as
Ad hoc updates to system catalogs are not allowed.
Please tell me if there is a way to delete multiples in SQL Server?
You can use dynamic query to DROP the required tables:
DECLARE #ExecSQL AS NVARCHAR (MAX) = '';
SELECT #ExecSQL = #ExecSQL +
'DROP TABLE ' + QUOTENAME(S.name) + '.' + QUOTENAME(T.name) + '; '
FROM sys.tables T
JOIN sys.schemas S ON S.schema_id = T.schema_id
WHERE T.name LIKE '%DynamicSurgery'
--PRINT #ExecSQL
EXEC (#ExecSQL)
EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL';
EXEC sp_MSforeachtable 'IF OBJECT_ID(''?'') NOT IN (
ISNULL(OBJECT_ID(''[dbo].[Table1]''),0),
ISNULL(OBJECT_ID(''[dbo].[Table2]''),0)
)
DELETE FROM ?';
EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL';
select the table by clicking on it
press the delete button and hit enter.
Take note : if there is any dependencies(Foreign Key), the table will not be deleted
I'm using Microsoft SQL Server and it seems that I cannot get around this issue.
I have a table on which I will have some dynamic and static columns.
Static columns would be name of product, type of product and the dynamic data would be some production data from ongoing months.
At the every beginning of the month I have to drop from the dynamic columns the past month and add a new month to the end of the table
My solution was saving the name of the column into a local variable and then adding it to the alter statement. But this does not work , it keeps giving me a error as under:
Msg 102, Level 15, State 1, Line 18
Incorrect syntax near '#month_b'
I will now add the queries
declare #month_t char(15)
declare #month_b char(15)
declare #sql char(30)
set #month_b = (SELECT top 1 name
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.ct_test')
AND name != 'TTNR' AND name != 'Family' AND name like '%B%'
ORDER BY name ASC)
set #month_t = (SELECT top 1 name
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.ct_test')
AND name != 'TTNR' AND name != 'Family' AND name like '%T%'
ORDER BY name ASC)
alter table ct_test
drop column #month_b
I cannot find a solution to this, can you help me.
Thank you in advance
You need to use Dynamic Query
Declare #sql nvarchar(max)
set #sql = 'alter table ct_test drop column '+ #month_b
Exec sp_executesql #sql
set #sql = 'alter table ct_test drop column '+ #month_t
Exec sp_executesql #sql
I am trying to copy rows from one column to another. Execution flow is simple.
Check if column is exist.
If not - add column
Define cursor and populate rows for new column
Set column to NOT NULL.
Unfortunately I am getting this type of error. It says that column does not exist. But I've created it and committed transaction. What could be a reason? Thanks!
Msg 207, Level 16, State 1, Line 29
Invalid column name 'Field_Name'.
Code:
begin transaction;
IF NOT EXISTS(SELECT * FROM sys.columns
WHERE Name = N'Field_Name' and Object_ID = Object_ID(N'dbo.Table_Name'))
BEGIN
ALTER TABLE [dbo].[Table_Name]
ADD [Field_Name] VARCHAR(255)
END
commit;
DECLARE
#var1 int,
#var2 varchar(255)
DECLARE copy_cursor CURSOR FOR
SELECT id, Name
FROM Table_Name
OPEN copy_cursor
FETCH NEXT FROM copy_cursor
INTO #var1, #var2
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE Table_Name
SET Field_Name = #var2
WHERE id = #var1
FETCH NEXT FROM copy_cursor
INTO #var1, #var2
END
CLOSE copy_cursor;
DEALLOCATE copy_cursor;
ALTER TABLE Table_Name ALTER COLUMN Field_name varchar(255) NOT NULL
The server tries to compile an entire batch of SQL before it runs any of it. So, before referencing the column in a query, you need to create it (if necessary) in a separate batch. Insert a GO keyword to instruct your tool (SQLCMD, OSQL, SSMS) to send separate batches:
begin transaction;
IF NOT EXISTS(SELECT * FROM sys.columns
WHERE Name = N'Field_Name' and Object_ID = Object_ID(N'dbo.Table_Name'))
BEGIN
ALTER TABLE [dbo].[Table_Name]
ADD [Field_Name] VARCHAR(255)
END
commit;
GO
I think you may also need to wrap the ALTER as follows, to deal with the case where the column does exist:
EXEC sp_executesql 'ALTER TABLE [dbo].[Table_Name]
ADD [Field_Name] VARCHAR(255)'
First check if the table exists, start and commit the transaction, and it should work.
BEGIN TRANSACTION
IF (Object_ID(N'dbo.Table_Name') > 0)
BEGIN
IF NOT EXISTS(SELECT * FROM sys.columns
WHERE Name = N'Field_Name' and Object_ID = Object_ID(N'dbo.Table_Name'))
BEGIN
ALTER TABLE [dbo].[Table_Name]
ADD [Field_Name] VARCHAR(255)
END
END
COMMIT
GO