In Microsoft SQL Server, I know the query to check if a default constraint exists for a column and drop a default constraint is:
IF EXISTS(SELECT * FROM sysconstraints
WHERE id=OBJECT_ID('SomeTable')
AND COL_NAME(id,colid)='ColName'
AND OBJECTPROPERTY(constid, 'IsDefaultCnst')=1)
ALTER TABLE SomeTable DROP CONSTRAINT DF_SomeTable_ColName
But due to typo in previous versions of the database, the name of the constraint could be DF_SomeTable_ColName or DF_SmoeTable_ColName.
How can I delete the default constraint without any SQL errors? Default constraint names don't show up in INFORMATION_SCHEMA table, which makes things a bit trickier.
So, something like 'delete the default constraint in this table/column', or 'delete DF_SmoeTable_ColName', but don't give any errors if it can't find it.
Expanding on Mitch Wheat's code, the following script will generate the command to drop the constraint and dynamically execute it.
declare #schema_name nvarchar(256)
declare #table_name nvarchar(256)
declare #col_name nvarchar(256)
declare #Command nvarchar(1000)
set #schema_name = N'MySchema'
set #table_name = N'Department'
set #col_name = N'ModifiedDate'
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
--print #Command
execute (#Command)
Rob Farley's blog post might be of help:
Two ways to find / drop a default constraint without knowing its name
Something like:
declare #table_name nvarchar(256)
declare #col_name nvarchar(256)
set #table_name = N'Department'
set #col_name = N'ModifiedDate'
select t.name, c.name, d.name, d.definition
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 c.name = #col_name
I found that this works and uses no joins:
DECLARE #ObjectName NVARCHAR(100)
SELECT #ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + #ObjectName)
Just make sure that columnName does not have brackets around it because the query is looking for an exact match and will return nothing if it is [columnName].
To drop constraint for multiple columns:
declare #table_name nvarchar(256)
declare #Command nvarchar(max) = ''
set #table_name = N'ATableName'
select #Command = #Command + 'ALTER TABLE ' + #table_name + ' drop constraint ' + d.name + CHAR(10)+ CHAR(13)
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 c.name in ('column1','column2','column3')
--print #Command
execute (#Command)
Expanded solution (takes table schema into account):
-- Drop default contstraint for SchemaName.TableName.ColumnName
DECLARE #schema_name NVARCHAR(256)
DECLARE #table_name NVARCHAR(256)
DECLARE #col_name NVARCHAR(256)
DECLARE #Command NVARCHAR(1000)
set #schema_name = N'SchemaName'
set #table_name = N'TableName'
set #col_name = N'ColumnName'
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.schemas s
ON s.schema_id = t.schema_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 s.name = #schema_name
AND c.name = #col_name
EXECUTE (#Command)
Run this command to browse all constraints:
exec sp_helpconstraint 'mytable' --and look under constraint_name.
It will look something like this: DF__Mytable__Column__[ABC123]. Then you can just drop the constraint.
Drop all default contstraints in a database - safe for nvarchar(max) threshold.
/* WARNING: THE SAMPLE BELOW; DROPS ALL THE DEFAULT CONSTRAINTS IN A DATABASE */
/* MAY 03, 2013 - BY WISEROOT */
declare #table_name nvarchar(128)
declare #column_name nvarchar(128)
declare #df_name nvarchar(128)
declare #cmd nvarchar(128)
declare table_names cursor for
SELECT t.name TableName, c.name ColumnName
FROM sys.columns c INNER JOIN
sys.tables t ON c.object_id = t.object_id INNER JOIN
sys.schemas s ON t.schema_id = s.schema_id
ORDER BY T.name, c.name
open table_names
fetch next from table_names into #table_name , #column_name
while ##fetch_status = 0
BEGIN
if exists (SELECT top(1) 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 c.name = #column_name)
BEGIN
SET #df_name = (SELECT top(1) 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 c.name = #column_name)
select #cmd = 'ALTER TABLE [' + #table_name + '] DROP CONSTRAINT [' + #df_name + ']'
print #cmd
EXEC sp_executeSQL #cmd;
END
fetch next from table_names into #table_name , #column_name
END
close table_names
deallocate table_names
I hope this could be helpful for whom has similar problem .
In ObjectExplorer window, select your database=> Tables,=> your table=> Constraints. If the customer is defined on create column time, you can see the default name of constraint including the column name.
then use:
ALTER TABLE yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;
(the constraint name is just an example)
Following solution will drop specific default constraint of a column from the table
Declare #Const NVARCHAR(256)
SET #Const = (
SELECT TOP 1 'ALTER TABLE' + YOUR TABLE NAME +' DROP CONSTRAINT '+name
FROM Sys.default_constraints A
JOIN sysconstraints B on A.parent_object_id = B.id
WHERE id = OBJECT_ID('YOUR TABLE NAME')
AND COL_NAME(id, colid)='COLUMN NAME'
AND OBJECTPROPERTY(constid,'IsDefaultCnst')=1
)
EXEC (#Const)
declare #ery nvarchar(max)
declare #tab nvarchar(max) = 'myTable'
declare #qu nvarchar(max) = 'alter table '+#tab+' drop constraint '
select #ery = (select bj.name from sys.tables as tb
inner join sys.objects as bj
on tb.object_id = bj.parent_object_id
where tb.name = #tab and bj.type = 'PK')
exec(#qu+#ery)
Take a look.
I had some columns that had multiple default constraints created, so I create the following stored procedure:
CREATE PROCEDURE [dbo].[RemoveDefaultConstraints] #table_name nvarchar(256), #column_name nvarchar(256)
AS
BEGIN
DECLARE #ObjectName NVARCHAR(100)
START: --Start of loop
SELECT
#ObjectName = OBJECT_NAME([default_object_id])
FROM
SYS.COLUMNS
WHERE
[object_id] = OBJECT_ID(#table_name)
AND [name] = #column_name;
-- Don't drop the constraint unless it exists
IF #ObjectName IS NOT NULL
BEGIN
EXEC ('ALTER TABLE '+#table_name+' DROP CONSTRAINT ' + #ObjectName)
GOTO START; --Used to loop in case of multiple default constraints
END
END
GO
-- How to run the stored proc. This removes the default constraint(s) for the enabled column on the User table.
EXEC [dbo].[RemoveDefaultConstraints] N'[dbo].[User]', N'enabled'
GO
-- If you hate the proc, just get rid of it
DROP PROCEDURE [dbo].[RemoveDefaultConstraints]
GO
Useful for some columns that had multiple default constraints or check constraints created:
Modified https://stackoverflow.com/a/16359095/206730 script
Note: this script is for sys.check_constraints
declare #table_name nvarchar(128)
declare #column_name nvarchar(128)
declare #constraint_name nvarchar(128)
declare #constraint_definition nvarchar(512)
declare #df_name nvarchar(128)
declare #cmd nvarchar(128)
PRINT 'DROP CONSTRAINT [Roles2016.UsersCRM].Estado'
declare constraints cursor for
select t.name TableName, c.name ColumnName, d.name ConstraintName, d.definition ConstraintDefinition
from sys.tables t
join sys.check_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 = N'Roles2016.UsersCRM' and c.name = N'Estado'
open constraints
fetch next from constraints into #table_name , #column_name, #constraint_name, #constraint_definition
while ##fetch_status = 0
BEGIN
print 'CONSTRAINT: ' + #constraint_name
select #cmd = 'ALTER TABLE [' + #table_name + '] DROP CONSTRAINT [' + #constraint_name + ']'
print #cmd
EXEC sp_executeSQL #cmd;
fetch next from constraints into #table_name , #column_name, #constraint_name, #constraint_definition
END
close constraints
deallocate constraints
Always generate script and review before you run. Below the script
select 'Alter table dbo.' + t.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 c.name in ('VersionEffectiveDate','VersionEndDate','VersionReasonDesc')
order by t.name
declare #table_name nvarchar(100)
declare #col_name nvarchar(100)
declare #constraint nvarchar(100)
set #table_name = N'TableName'
set #col_name = N'ColumnName'
IF EXISTS (select c.*
from sys.columns c
inner join sys.tables t on t.object_id = c.object_id
where t.name = #table_name
and c.name = #col_name)
BEGIN
select #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 c.name = #col_name
IF LEN(ISNULL(#constraint, '')) <> 0
BEGIN
DECLARE #sqlcmd VARCHAR(MAX)
SET #sqlcmd = 'ALTER TABLE ' + QUOTENAME(#table_name) + ' DROP CONSTRAINT' +
QUOTENAME(#constraint);
EXEC (#sqlcmd);
END
END
GO
This will check if the foreign key exists or not. If it exists, then drop that.
DECLARE #SCHEMA_NAME NVARCHAR(256)
-- The table name you what drop the foreign key from.
DECLARE #ALTER_TABLE_NAME NVARCHAR(256)
-- The table name is liked with the foreign key.
DECLARE #REF_TABLE_NAME NVARCHAR(256)
DECLARE #COMMAND NVARCHAR(MAX)
SET #SCHEMA_NAME = N'MySchema';
SET #ALTER_TABLE_NAME = N'MyAlterTable';
SET #REF_TABLE_NAME = N'MyReferTable';
IF EXISTS (
SELECT NAME
FROM SYS.FOREIGN_KEYS
WHERE PARENT_OBJECT_ID = (
SELECT OBJECT_ID
FROM SYS.OBJECTS
WHERE OBJECT_ID = OBJECT_ID(#ALTER_TABLE_NAME)
)
AND REFERENCED_OBJECT_ID = (
SELECT OBJECT_ID
FROM SYS.OBJECTS
WHERE OBJECT_ID = OBJECT_ID(#REF_TABLE_NAME)
)
)
BEGIN
SELECT #COMMAND = 'ALTER TABLE ['
+ #SCHEMA_NAME
+ '].['
+ #ALTER_TABLE_NAME
+ '] DROP CONSTRAINT '
+ NAME
FROM SYS.FOREIGN_KEYS
WHERE PARENT_OBJECT_ID = (
SELECT OBJECT_ID
FROM SYS.OBJECTS
WHERE OBJECT_ID = OBJECT_ID(#ALTER_TABLE_NAME)
)
AND REFERENCED_OBJECT_ID = (
SELECT OBJECT_ID
FROM SYS.OBJECTS
WHERE OBJECT_ID = OBJECT_ID(#REF_TABLE_NAME)
)
EXECUTE (#COMMAND)
END
GO
Here is a simple solution, just replace your_table and the column_name.
DECLARE #var0 nvarchar(128)
SELECT #var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'${default_schema}.your_table')
AND col_name(parent_object_id, parent_column_id) = 'column_name';
IF #var0 IS NOT NULL
EXECUTE ('ALTER TABLE ${default_schema}.your_table DROP CONSTRAINT [' + #var0 + ']');
GO
Related
I was looking this article
and I have just a question how to add IFEXISTS() in the select part:
I want to run #command only if there some rows. I think it will throw an error if I dont check select part?
declare #table_name nvarchar(256)
declare #Command nvarchar(max) = ''
set #table_name = N'ATableName'
select #Command = #Command + 'ALTER TABLE ' + #table_name + ' drop constraint ' + d.name + CHAR(10)+ CHAR(13)
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 c.name in ('column1','column2','column3')
--print #Command
execute (#Command)
I have this script which finds all tables that contain data in column RGNCODE. I'm trying to amend this to find tables that contain a specific value for rgncode across all tables. So RGNCODE = 'UK'. Unsure where to add this in?
SELECT
sys.columns.name AS ColumnName,
tables.name AS TableName
FROM sys.columns
JOIN sys.tables ON sys.columns.object_id = tables.object_id
WHERE
sys.columns.name = 'rgncode' and
tables.name in (
SELECT [TableName] = so.name
FROM sysobjects so, sysindexes si
WHERE so.xtype = 'U' AND si.id = so.id
GROUP BY so.name
HAVING max(si.rows) > 0
)
A dynamic statement, using system catalog views, is an option here:
DECLARE #stm nvarchar(max) = N''
SELECT #stm = #stm +
CASE WHEN #stm = N'' THEN '' ELSE N'UNION ALL ' END +
N'SELECT ''' +
QUOTENAME(sch.[name]) + '.' + QUOTENAME(tab.[name]) + ''' AS TableName FROM ' +
QUOTENAME(sch.[name]) + '.' + QUOTENAME(tab.[name]) +
N' WHERE RGNCODE = ''UK'' HAVING COUNT(*) > 0 '
FROM sys.columns col
JOIN sys.tables tab ON col.object_id = tab.object_id
JOIN sys.schemas sch ON tab.schema_id = sch.schema_id
WHERE col.[name] = 'RGNCODE'
PRINT #stm
EXEC sp_executesql #stm
I think the following cursor will help you:
CREATE TABLE ##DataTable
(TblName VARCHAR(100),RowNum INT)
GO
DECLARE #TableName AS VARCHAR(200)
DECLARE #SQLText AS nVARCHAR(MAX)
DECLARE #TableCount AS INT
DECLARE TableDect CURSOR
FOR
SELECT
tables.name AS TableName
FROM
sys.columns
JOIN sys.tables ON
sys.columns.object_id = tables.object_id
WHERE
sys.columns.name = 'rgncode' and tables.name in (
SELECT
[TableName] = so.name
FROM
sysobjects so,
sysindexes si
WHERE
so.xtype = 'U'
AND
si.id = so.id
GROUP BY
so.name
HAVING max(si.rows) >0 )
OPEN TableDect
FETCH NEXT FROM TableDect INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQLText = N'SELECT #NumberOUT=COUNT(*) FROM ' + QUOTENAME(#TableName) + ' WHERE rgncode=''UK'''
SET #TableCount = 0
EXECUTE sp_executesql #SQLText ,N'#NumberOUT nvarchar(25) OUTPUT' ,#NumberOUT=#TableCount OUTPUT
INSERT INTO ##DataTable values(#TableName,#TableCount)
FETCH NEXT FROM TableDect INTO #TableName
END
CLOSE TableDect;
DEALLOCATE TableDect
SELECT * FROM ##DataTable
I have a distributed application that lives at many customer sites. The previous developer was not very good in giving user defined names to constraints. How could I go about renaming all the constrains to something like 'DF_[TableName]_[ColumnName]'? I could try and cursor over the list of tables. Do you think this would be a problem if I deploy this to a customer site? Or is there a better way to accomplish this?
SELECT sys.schemas.name as [Schema],
sys.tables.name as [TableName],
sys.all_columns.name as [Column],
default_constraints.name as [Constraint]
FROM
sys.all_columns
INNER JOIN sys.tables
ON all_columns.object_id = tables.object_id
INNER JOIN sys.schemas
ON tables.schema_id = schemas.schema_id
INNER JOIN sys.default_constraints
ON all_columns.default_object_id = default_constraints.object_id
where default_constraints.name like '%[0-9]%'
If you are using a naming convention for each constraint type, then this would help you. Here I am putting an example of how to handle this with Default constraint. The procedure will find default constraints, drop those that don't follow naming conventions and create new ones with the old one's definition.
This is a simple version for one time run
DECLARE #SchemaName sysname = 'dbo';
DECLARE #TableName sysname = NULL;
DECLARE #ColumnName sysname = NULL;
DECLARE #sql VARCHAR(max) = '';
SELECT
#sql +=
'ALTER TABLE [' + s.name + '].[' + o.name + '] DROP CONSTRAINT [' + dc.name + ']; ' +
'ALTER TABLE [' + s.name + '].[' + o.name + '] ADD CONSTRAINT [DF_' + o.name + '_' + c.name + '] DEFAULT ' + dc.DEFINITION + ' FOR [' + c.name + '];'
FROM dbo.sysobjects do
INNER JOIN dbo.sysobjects o ON do.parent_obj = o.id
INNER JOIN sys.default_constraints dc ON dc.object_id = do.id
INNER JOIN sys.columns c ON c.object_id = o.id
AND c.column_id = dc.parent_column_id
INNER JOIN sys.schemas s ON s.schema_id = dc.schema_id
WHERE o.type = 'U'
AND do.type = 'D'
AND s.name = #SchemaName
AND o.name = CASE WHEN ISNULL(#TableName,'') = ''
THEN o.name
ELSE #TableName END
AND c.name = CASE WHEN ISNULL(#ColumnName,'') = ''
THEN c.name
ELSE #ColumnName END
AND do.name NOT LIKE 'DF_' + o.name + '_' + c.name
ORDER BY o.name
--PRINT (#sql)
EXECUTE(#sql)
And this is a procedure in case you want to keep running the procedure every once in a while
USE [YourDatabaseName]
GO
-- Check if the procedure exists and drop it if so
IF EXISTS (SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[usp_NamingConventionDefaultConstraint]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[usp_NamingConventionDefaultConstraint]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--procedure can be used for specific schema/table/columns or those can be left null to include everything.
CREATE PROC [dbo].[usp_NamingConventionDefaultConstraint]
#SchemaName sysname = 'dbo',
#TableName sysname = NULL,
#ColumnName sysname = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql VARCHAR(max)
DECLARE GetIndexes CURSOR
FOR
SELECT
--here drop the old constraint and create a new one with the old's definition
'ALTER TABLE [' + s.name + '].[' + o.name + '] DROP CONSTRAINT [' + dc.name + ']; ' +
'ALTER TABLE [' + s.name + '].[' + o.name + '] ADD CONSTRAINT [DF_' + o.name + '_' + c.name + '] DEFAULT ' + dc.DEFINITION + ' FOR [' + c.name + '];'
AS dc_alter
FROM dbo.sysobjects do
INNER JOIN dbo.sysobjects o ON do.parent_obj = o.id
INNER JOIN sys.default_constraints dc ON dc.object_id = do.id
INNER JOIN sys.columns c ON c.object_id = o.id
AND c.column_id = dc.parent_column_id
INNER JOIN sys.schemas s ON s.schema_id = dc.schema_id
WHERE o.type = 'U'
-- work only on default constraints
AND do.type = 'D'
AND s.name = #SchemaName
AND o.name = CASE WHEN ISNULL(#TableName,'') = '' THEN o.name ELSE #TableName END
AND c.name = CASE WHEN ISNULL(#ColumnName,'') = '' THEN c.name ELSE #ColumnName END
-- here goes the naming convention you have in mind
--DF_TableName_ColumnName
AND do.name NOT LIKE 'DF_' + o.name + '_' + c.name
ORDER BY o.name
OPEN GetIndexes
FETCH NEXT FROM GetIndexes
INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
IF ISNULL(#sql,'')<>''
BEGIN
EXEC (#sql)
END
FETCH NEXT FROM GetIndexes
INTO #sql
END
CLOSE GetIndexes
DEALLOCATE GetIndexes
END
GO
We're looking to do an update in several SQL Server databases to change all NULL values in a certain table to be empty strings instead of NULL. We're potentially going to be doing this across hundreds of databases. The table name will always be the same, but the column names are variable based on how the front-end application is configured (don't judge... I didn't create this system).
Is there a way to do an update on all of these columns without knowing the column names ahead of time?
You can pass the name of the column in dynamic sql:
declare #sql nvarchar (1000);
set #sql = N'update table set ' + #column_name + '= ''''';
exec sp_executesql #sql;
You can look in the sys.columns table and join on the table name or object_id.
DECLARE #OBJ_ID INT
SELECT #OBJ_ID = OBJECT_ID
FROM SYS.tables
WHERE name = 'YOURTABLE'
SELECT * FROM SYS.columns
WHERE OBJECT_ID = #OBJ_ID
You could use the name field from the sys.columns query as a basis to perform the update on.
Assuming you want all columns of varchar/char types only (or change the type filter to whatever you need):
DECLARE #tableName varchar(10)
SET #tableName = 'yourtablenamehere'
DECLARE #sql VARCHAR(MAX)
SET #sql = ''
SELECT #sql = #sql + 'UPDATE ' + #tableName + ' SET ' + c.name + ' = '''' WHERE ' + c.name + ' IS NULL ;'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE t.name = #tableName AND y.name IN ('varchar', 'nvarchar', 'char', 'nchar')
EXEC (#sql)
This can be achieved with cursors. You first select the column names like #Darren mentioned, then you Set a Cursor with those values and loop:
Open oColumnsCursor
Fetch Next From oColumnscursor
Into #ColumnName
While ##FETCH_STATUS=0
Begin
Set #oQuery = 'Update [DB]..[Table] Set [' + #ColumnName + '] = ''NewValue'' Where [' + #ColumnName + '] = ''OldValue'''
Execute(#oQuery)
Fetch Next From oColumnscursor Into #ColumnName
Set #oCount = #oCount + 1
End
Close oColumnsCursor;
Deallocate oColumnsCursor;
This will work when you know the Table Name:
DECLARE #tableName varchar(10)
SET #tableName = 'Customers'
DECLARE #sql VARCHAR(MAX)
SET #sql = ''
SELECT #sql = #sql + 'UPDATE ' + #tableName + ' SET ' + c.name + ' = ISNULL('+ c.name +','''');'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE y.name IN ('varchar', 'nvarchar', 'char', 'nchar')
AND t.name = #tableName;
EXEC(#sql);
And this will iterate all Tables and all Columns in a Db:
DECLARE #sql VARCHAR(MAX)
SET #sql = ''
SELECT #sql = #sql + 'UPDATE ' + t.name + ' SET ' + c.name + ' = ISNULL('+ c.name +','''');'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE y.name IN ('varchar', 'nvarchar', 'char', 'nchar');
EXEC(#sql);
Below is the procedure.
ALTER PROCEDURE [dbo].[util_db_updateRow]
#colval_name NVARCHAR (30), -- column and values e.g. tax='5.50'
#idf_name NVARCHAR (300), -- column name
#idn_name NVARCHAR (300), -- column value
#tbl_name NVARCHAR (100) -- table name
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX)
-- construct SQL
SET #sql = 'UPDATE ' + #tbl_name + ' SET ' + #colval_name +
' WHERE ' + #idf_name + '=' + #idn_name;
-- execute the SQL
EXEC sp_executesql #sql
SET NOCOUNT OFF
RETURN
END
Below is the stored procedure where you can pass Schema Name, Table Name and list of column names separted by comma.It works only in Sql Server 2016 or higher.
CREATE OR ALTER PROCEDURE UpdateData
(#SchemaName NVARCHAR(Max),#TableName NVARCHAR(MAX),#ColumnNames NVARCHAR(MAX))
AS
BEGIN
DECLARE #DynamicSql NVARCHAR(MAX);
SET #DynamicSql = 'UPDATE ' +'[' +#SchemaName+'].' + '[' +#TableName+']' +' SET ' + STUFF((SELECT ', [' + C.name + '] = ' + '''NEW_VALUE'''
FROM sys.columns C
INNER JOIN sys.tables T ON T.object_id = C.object_id
INNER JOIN sys.schemas S ON T.schema_id = S.schema_id
WHERE
T.name = #TableName
AND S.Name = #SchemaName
AND [C].[name] in (SELECT VALUE FROM string_split(#ColumnNames,','))
FOR XML PATH('')), 1,1, '')
print #DynamicSql;
EXEC (#DynamicSql);
END
I've created some foreign keys without an explicit name.
Then I've found SQL generated crazy names like FK__Machines__IdArt__760D22A7. Guess they will be generated with different names at different servers.
Is there any nice function to drop the unnamed FK constraints passing as arguments the tables and the fields in question?
For dropping an individual unnamed default constrain on a column use the following code:
DECLARE #ConstraintName VARCHAR(256)
SET #ConstraintName = (
SELECT obj.name
FROM sys.columns col
LEFT OUTER JOIN sys.objects obj
ON obj.object_id = col.default_object_id
AND obj.type = 'F'
WHERE col.object_id = OBJECT_ID('TableName')
AND obj.name IS NOT NULL
AND col.name = 'ColunmName'
)
IF(#ConstraintName IS NOT NULL)
BEGIN
EXEC ('ALTER TABLE [TableName] DROP CONSTRAINT ['+#ConstraintName+']')
END
If you want to do this for a default column, which is probably more common than the original question and I'm sure a lot of people will land on this from a Google search, then just change the line:
obj.type = 'F'
to
obj.type = 'D'
There is not a built in procedure to accomplish this, but you can build your own using the information in the information_schema views.
Table based example
Create Proc dropFK(#TableName sysname)
as
Begin
Declare #FK sysname
Declare #SQL nvarchar(4000)
Declare crsFK cursor for
select tu.Constraint_Name from
information_schema.constraint_table_usage TU
LEFT JOIN SYSOBJECTS SO
ON TU.Constraint_NAME = SO.NAME
where xtype = 'F'
and Table_Name = #TableName
open crsFK
fetch next from crsFK into #FK
While (##Fetch_Status = 0)
Begin
Set #SQL = 'Alter table ' + #TableName + ' Drop Constraint ' + #FK
Print 'Dropping ' + #FK
exec sp_executesql #SQL
fetch next from crsFK into #FK
End
Close crsFK
Deallocate crsFK
End
Although Gunner's answer puts people on the right track if you want to drop an actual DEFAULT constraint rather than an FKey constraint (which is what brought ME here too!) there are problems with it.
I think this fixes them all. (T-SQL)
CREATE PROC #DropDefaultConstraint #SchemaName sysname, #TableName sysname, #ColumnName sysname
AS
BEGIN
DECLARE #ConstraintName sysname;
SELECT #SchemaName = QUOTENAME(#SchemaName)
, #TableName = QUOTENAME(#TableName);
SELECT #ConstraintName = QUOTENAME(o.name)
FROM sys.columns c
JOIN sys.objects o
ON o.object_id = c.default_object_id
WHERE c.object_id = OBJECT_ID(#SchemaName+'.'+#TableName)
AND c.name = #ColumnName;
IF #ConstraintName IS NOT NULL
EXEC ('ALTER TABLE ' + #SchemaName + '.' + #TableName + ' DROP CONSTRAINT ' + #ConstraintName + '');
END
This will let you drop a specific foreign key constraint based on tablename + column name
After trying out the other answers I just had a poke around in the system tables until I found something likely looking.
The one you want is Constraint_Column_Usage which according to the docs Returns one row for each column in the current database that has a constraint defined on the column.
I've joined it to sys.objects to just get foreign keys.
In a procedure (this borrows from the other answers. cheers guys!):
Create Proc yourSchema.dropFK(#SchemaName NVarChar(128), #TableName NVarChar(128), #ColumnName NVarChar(128))
as
Begin
DECLARE #ConstraintName nvarchar(128)
SET #ConstraintName = (
select c.Constraint_Name
from Information_Schema.Constraint_Column_usage c
left join sys.objects o
on o.name = c.Constraint_Name
where c.TABLE_SCHEMA = #SchemaName and
c.Table_name = #TableName and
c.Column_Name = #ColumnName and
o.type = 'F'
)
exec ('alter table [' + #SchemaName + '].[' + #TableName + '] drop constraint [' + #ConstraintName + ']')
End
Neither of these worked for me so I had to come up with this to work on mssql server version both 12 and 14.
First, inspect the name given to the FK by the RDBMS, it has the same prefix and body but differs only in suffix hash.
Second, select names of these constraints.
Third, exec alter command that drops them.
Finally you can drop the column or table blocked by these
BEGIN TRANSACTION;
DECLARE #ConstraintName nvarchar(200)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut1___%'
EXEC('ALTER TABLE table1 DROP CONSTRAINT ' + #ConstraintName)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut2___%'
EXEC('ALTER TABLE table2 DROP CONSTRAINT ' + #ConstraintName)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut3___%'
EXEC('ALTER TABLE table3 DROP CONSTRAINT ' + #ConstraintName)
DROP TABLE table_referenced;
COMMIT TRANSACTION;
Lesson learnt, I will always create constraints explicitly from now on!
This will generate a script to rename default constraints to use the pattern
DF__table_name__column_name
SELECT 'EXEC sp_rename ''dbo.' + dc.name + ''', ''DF__' + t.name + '__' + c.name + '''' AS the_script,
t.name AS table_name,
c.name AS column_name,
dc.name AS old_constraint_name
FROM
sys.default_constraints dc
INNER JOIN sys.tables t
ON dc.parent_object_id = t.object_id
INNER JOIN sys.columns c
ON dc.parent_column_id = c.column_id
AND t.object_id = c.object_id
WHERE
dc.name <> 'DF__' + t.name + '__' + c.name