I have custom default value in a SQL server 2008 table.
Similar to this
CREATE DEFAULT [dbo].[Default_Timestamp]
AS
GetDate()
Now I want to change the value in that default.
CREATE DEFAULT [dbo].[Default_Timestamp]
AS
GETUTCDATE()
Before I can edit the existing one, I need to drop the first one and recreate it.
DROP DEFAULT [dbo].[Default_Timestamp]
it gives following error.
Msg 3716, Level 16, State 3, Line 4
The default 'dbo.Default_Timestamp' cannot be dropped because it is bound to one or more column.
Since the default is already use by few tables I cannot drop and recreate a new one.
I know I need to unbind all the tables from this default before I can recreate it.
Can anyone provide a script to list all the table and columns which are bound with that default?
It's a multi-step process:
1) Find the object_id for your default :
DECLARE #DefaultObjectID INT
SELECT #DefaultObjectID = OBJECT_ID('Default_Timestamp')
2) Find all the columns that reference that default:
SELECT
ColumnName = c.Name,
TableName = t.Name,
UnbindCmd = 'EXEC sp_unbindefault ''' + t.Name + '.' + c.name + ''''
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE default_object_id = #DefaultObjectID
This will produce a list of UnbindCmd commands to actually remove the DEFAULT from those columns.
3) Now, copy that column from your SQL Server Mgmt Studio window, and execute it in a new query window to actually "unbind" the default from all those columns
4) Now define your new default
However: these days, I would probably not define a new DEFAULT per se - can't you just set the default constraint on the columns in question directly?
ALTER TABLE dbo.YourTable
ADD CONSTRAINT DF_YourTable_TimeStamp
DEFAULT GETUTCDATE() FOR YourColumnName
Seems a like easier to work with going into the future! When you explicitly name your constraint, you can also easily find and drop that constraint again, if need be.
I ran across this issue when I found some old style defaults in my database where I had to update uses_ansi_nulls and uses_quoted_identifier en mass in my database.
Here is the code that I ended up writing to replace the old style defaults (CREATE DEFAULT sp_BindDefault) with the newer style (ALTER TABLE).
DECLARE #strSQL varchar(max)
, #DBName varchar(50) = DB_NAME();
DROP TABLE IF EXISTS #tmp;
SELECT IDENTITY(int, 1,1) AS ID,
UnbindCmd = 'EXEC sp_unbindefault ''' + t.Name + '.' + c.name + ''';',
DropCmd = 'DROP DEFAULT IF EXISTS [' + SCHEMA_NAME(SO.schema_id) + '].[' + OBJECT_NAME(SO.object_id) + '];',
CreateCmd = 'ALTER TABLE [' + SCHEMA_NAME(t.Schema_id) + '].[' + t.Name + ']'
+ ' ADD CONSTRAINT df_' + REPLACE(t.Name, ' ', '') + '_' + REPLACE(c.Name, ' ', '')
+ ' DEFAULT (' + RIGHT(m.definition, LEN(m.definition) - CHARINDEX(' AS ', m.definition) - 3)
+ ') FOR ' + QUOTENAME(c.Name) + ';'
INTO #tmp
FROM sys.sql_modules m
join sys.columns c on c.default_object_id = m.object_id
INNER JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.objects SO ON SO.object_id = C.default_object_id
WHERE (m.uses_ansi_nulls = 0
OR m.uses_quoted_identifier = 0)
ORDER BY
t.name
, c.name;
BEGIN TRANSACTION
BEGIN TRY
DECLARE UnbindCursor CURSOR LOCAL FAST_FORWARD
FOR SELECT UnbindCmd
FROM #tmp
ORDER BY
ID;
OPEN UnbindCursor;
FETCH NEXT FROM UnbindCursor INTO #strSQL;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC (#strSQL);
FETCH NEXT FROM UnbindCursor INTO #strSQL;
END
CLOSE UnbindCursor;
DEALLOCATE UnbindCursor;
DECLARE DropCursor CURSOR LOCAL FAST_FORWARD
FOR SELECT DropCmd
FROM #tmp
GROUP BY
DropCmd
ORDER BY
MIN(id)
OPEN DropCursor;
FETCH NEXT FROM DropCursor INTO #strSQL;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC (#strSQL);
FETCH NEXT FROM DropCursor INTO #strSQL;
END
CLOSE DropCursor;
DEALLOCATE DropCursor;
DECLARE CreateCursor CURSOR LOCAL FAST_FORWARD
FOR SELECT CreateCmd
FROM #tmp
ORDER BY
id
OPEN CreateCursor;
FETCH NEXT FROM CreateCursor INTO #strSQL;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC (#strSQL);
FETCH NEXT FROM CreateCursor INTO #strSQL;
END
CLOSE CreateCursor;
DEALLOCATE CreateCursor;
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE #ErrorMessage nvarchar(4000)
, #ErrorSeverity int
, #ErrorState int;
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
END CATCH
I never saw CREATE DEFAULT or DROP DEFAULT as standalone commands, but only know the CONSTRAINT clause to add or drop a default constraint.
SSMS 2008 generates the following code (right click in table designer, "Generate Change Script..."):
ALTER TABLE dbo.T ADD CONSTRAINT
DF_T_DateTimeColumn DEFAULT getdate() FOR DateTimeColumn
GO
ALTER TABLE dbo.T
DROP CONSTRAINT DF_T_DateTimeColumn
GO
ALTER TABLE dbo.T ADD CONSTRAINT
DF_T_DateTimeColumn DEFAULT getutcdate() FOR DateTimeColumn
GO
update:
I admit it, I never used EXEC sp_bindefault, but I think its use is discouraged, as MSDN says:
This feature will be removed in a future version of Microsoft SQL
Server. Do not use this feature in new development work, and modify
applications that currently use this feature as soon as possible. We
recommend that you create default definitions by using the DEFAULT
keyword of the ALTER TABLE or CREATE TABLE statements instead.
This also applies to sp_unbindefault, of course.
You can find the columns that use a default object by looking at the default_object_id in sys.columns:
ID of the default object, regardless of whether it is a stand-alone
object sys.sp_bindefault, or an inline, column-level DEFAULT
constraint.
Knowing this is trivial to build a script that unbinds all columns from a default object and replaces the default with a constraint based default value:
use master;
go
if db_id('test') is not null
drop database test;
go
create database test;
go
use test;
go
create default foo as 1;
go
create table t1 (a int);
create table t2 (b int);
go
exec sp_bindefault 'foo', 't1.a';
exec sp_bindefault 'foo', 't2.b';
go
drop default foo;
-- Msg 3716, Level 16, State 3, Line 2
-- The default 'foo' cannot be dropped because it is bound to one or more column.
go
declare crs cursor static forward_only read_only for
select object_schema_name(object_id) as schema_name,
object_name(object_id) as object_name,
name as column_name
from sys.columns where default_object_id = object_id('foo');
open crs;
declare #schema_name sysname, #object_name sysname, #column_name sysname, #sql nvarchar(max);
fetch next from crs into #schema_name, #object_name, #column_name;
while ##fetch_status = 0
begin
set #sql = N'exec sp_unbindefault ' + quotename(
quotename(#schema_name) + N'.'+
quotename(#object_name) + N'.'+
quotename(#column_name), '''');
print #sql;
exec sp_executesql #sql;
set #sql = N'alter table ' +
quotename(#schema_name) + N'.' +
quotename(#object_name) + N' add constraint ' +
quotename(N'default_' + #column_name) + N' default 2 for ' +
quotename(#column_name);
print #sql;
exec sp_executesql #sql;
fetch next from crs into #schema_name, #object_name, #column_name;
end
close crs;
deallocate crs;
go
drop default foo;
-- it now succeeds
go
Related
I am trying to set a default value to a column(Inserted_time), but first i need to check if the column exists in the tables. If the column doesn't exist, I need to add that column and give it a default value.
I am working with Sql Server Management Studio.
So far I have written this code:
IF EXISTS ( select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_CATALOG = 'DB_COPY' and COLUMN_NAME = 'Inserted_Time')
begin
ALTER TABLE table_name ADD CONSTRAINT [Inserted_Time_Def] SET DEFAULT (sysdatetimeoffset()) FOR [Inserted_Time]
end
else
ALTER TABLE table_name ADD COLUMN [Inserted_Time] CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset()) WITH VALUES
Once I retrieve the tables that has the column, I need to add that table_name to the Alter command. But I am not able to do that. Can someone please tell me how to use the table_names retrieved from select statement in the alter statement?
First, you want to put all the table names in a temporary table so you can loop through it.
After, you can use a cursor to execute a command for each table name.
In my example, I only printed the command I wanted to execute. That way you can be sure the code will do what you want first.
Example :
select TABLE_NAME As TableName INTO #TablesList from INFORMATION_SCHEMA.COLUMNS where TABLE_CATALOG = 'DB_COPY' and COLUMN_NAME = 'Inserted_Time'
DECLARE #TablesCursor as CURSOR;
DECLARE #TableName as NVARCHAR(max);
DECLARE #CommandToExecute as NVARCHAR(max);
SET #TablesCursor = CURSOR FOR SELECT TableName FROM #TablesList;
OPEN #TablesCursor;
FETCH NEXT FROM #TablesCursor INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #CommandToExecute = 'ALTER TABLE ' + #TableName + ' WHAT YOU WANNA DO '
PRINT #CommandToExecute
--EXEC(#CommandToExecute)
FETCH NEXT FROM #TablesCursor INTO #TableName;
END
CLOSE #TablesCursor;
DEALLOCATE #TablesCursor;
Assuming that every table is in a different schema, then you could do something like this:
DECLARE #SQL nvarchar(MAX);
SET #SQL = STUFF((SELECT NCHAR(13) + NCHAR(10) +
CASE WHEN EXISTS (SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE T.TABLE_SCHEMA = C.TABLE_SCHEMA
AND T.TABLE_NAME = C.TABLE_SCHEMA
AND C.COLUMN_NAME = N'Inserted_Time') THEN N'ALTER TABLE ' + QUOTENAME(T.TABLE_SCHEMA) + N'.' + QUOTENAME(T.TABLE_NAME) + N' ADD CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset()) FOR [Inserted_Time];'
ELSE N'ALTER TABLE ' + QUOTENAME(T.TABLE_SCHEMA) + N'.' + QUOTENAME(T.TABLE_NAME) + N' ADD COLUMN [Inserted_Time] CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset());'
END
FROM INFORMATION_SCHEMA.TABLES T
WHERE T.TABLE_CATALOG = N'DB_COPY'
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,2,N'');
PRINT #SQL; --Your best friend. If more than 4,000 characters, use SELECT
EXECUTE sp_executesql #SQL;
This will very likely hugely out perform a CURSOR solution if you have a large number of schemas.
IF EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'LOCATION') AND type IN (N'P', N'PC'))
DROP PROCEDURE [dbo].[LOCATION]
GO
CREATE PROCEDURE [dbo].[LOCATION]
#IP NVARCHAR(100)
AS
BEGIN
DECLARE #IPNumber BIGINT
SELECT #IPNumber = dbo.ConvertIp2Num(#IP)
SELECT [country_code],[country_name]
FROM [myDatabase].[dbo].[CountryIP]
WHERE #IPNumber BETWEEN ip_from AND ip_to
END
I have the above code to check if stored procedure LOCATION exists in the current database. I expect it to drop and re-create the procedure if it exists.
However, if the procedure exists the code is still executing and as a result i get the following error 'There is already an object named 'LOCATION' in the database.'
Why is that code failing to drop the procedure if it exists?
The same code works properly for a another procedure in the same database.
Try this (preferred method using a view):
IF EXISTS(SELECT 1
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'PRC_NAME'
AND SPECIFIC_SCHEMA = 'schema_name')
BEGIN
DROP PROCEDURE PRC_NAME
END
or this (not recommended using direct access to a system table):
IF EXISTS (SELECT 1
FROM SYS.PROCEDURES
WHERE NAME = 'PRC_NAME'
AND SCHEMA_NAME(SCHEMA_ID) = 'SCHEMA_NAME'
AND [TYPE] IN (N'P',N'PC'))
BEGIN
DROP PROCEDURE PRC_NAME
END
Why the first method is preferred you can find out for example in this question: SQL Server: should I use information_schema tables over sys tables?
This is kind of late, but others that end up here might want to check out the MSDN documentation that say you could use:
DROP PROCEDURE IF EXISTS dbo.uspMyProc;
GO
This is however available from SQL Server 2016 Community Technology Preview 3.3 (CTP 3.3).
You could use:
IF OBJECT_ID('MSL_GET_IP_LOCATION', 'P') IS NOT NULL
DROP PROCEDURE MSL_GET_IP_LOCATION
GO
Further thought on this is you will need to make sure you have unique names across all objects.
SQL Server -
Drop List of Stored Procedures if existed on Customer DB +
Copy List of Stored Procedures from master to another DB (recreate dynamically). P.S.: #TargetDBName=your DB.
I hope it will help someone
--Drop SPs from Customer DB if existed---
DECLARE #TargetDBName NVARCHAR(255)
SET #TargetDBName = DB_NAME()
DECLARE #SQL NVARCHAR(max)
SET #SQL = ''
DECLARE v CURSOR
FOR
SELECT [NAME]
FROM [Master].[sys].[procedures] p WITH(NOLOCK)
INNER JOIN [Master].sys.sql_modules m WITH(NOLOCK) ON p.object_id = m.object_id
WHERE p.[NAME] LIKE 'mySPs_list_%'
AND [type] = 'P'
OPEN v
FETCH NEXT
FROM v
INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = REPLACE(#sql, '''', '''''')
SET #sql = 'USE [' + #TargetDBName + ']; IF OBJECT_ID('''+#sql+''', ''P'') IS NOT NULL DROP PROCEDURE '+ #sql+';'
EXEC SP_EXECUTESQL #sql
FETCH NEXT
FROM v
INTO #sql
END
CLOSE v
DEALLOCATE v;
--COPY SPs from master to Another DB-------------
DECLARE c CURSOR
FOR
SELECT [Definition]
FROM [Master].[sys].[procedures] p
INNER JOIN [Master].sys.sql_modules m ON p.object_id = m.object_id
WHERE p.[NAME] LIKE 'mySPs_list_%'
AND [type] = 'P'
OPEN c
FETCH NEXT
FROM c
INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = REPLACE(#sql, '''', '''''')
SET #sql = 'USE [' + #TargetDBName + ']; EXEC(''' + #sql + ''')'
EXEC SP_EXECUTESQL #sql
FETCH NEXT
FROM c
INTO #sql
END
CLOSE c
DEALLOCATE c;
I'm trying to write a script that will completely empty a SQL Server database. This is what I have so far:
USE [dbname]
GO
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DELETE ?'
When I run it in the Management Studio, I get:
Command(s) completed successfully.
but when I refresh the table list, they are all still there. What am I doing wrong?
You can also delete all tables from database using only MSSMS UI tools (without using SQL script). Sometimes this way can be more comfortable (especially if it is performed occasionally)
I do this step by step as follows:
Select 'Tables' on the database tree (Object Explorer)
Press F7 to open Object Explorer Details view
In this view select tables which have to be deleted (in this case all of them)
Keep pressing Delete until all tables have been deleted (you repeat it as many times as amount of errors due to key constraints/dependencies)
It doesn't work for me either when there are multiple foreign key tables.
I found that code that works and does everything you try (delete all tables from your database):
DECLARE #Sql NVARCHAR(500) DECLARE #Cursor CURSOR
SET #Cursor = CURSOR FAST_FORWARD FOR
SELECT DISTINCT sql = 'ALTER TABLE [' + tc2.TABLE_SCHEMA + '].[' + tc2.TABLE_NAME + '] DROP [' + rc1.CONSTRAINT_NAME + '];'
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME =rc1.CONSTRAINT_NAME
OPEN #Cursor FETCH NEXT FROM #Cursor INTO #Sql
WHILE (##FETCH_STATUS = 0)
BEGIN
Exec sp_executesql #Sql
FETCH NEXT FROM #Cursor INTO #Sql
END
CLOSE #Cursor DEALLOCATE #Cursor
GO
EXEC sp_MSforeachtable 'DROP TABLE ?'
GO
You can find the post here. It is the post by Groker.
In SSMS:
Right click the database
Go to "Tasks"
Click "Generate Scripts"
In the "Choose Objects" section, select "Script entire database and all database objects"
In the "Set Scripting Options" section, click the "Advanced" button
On "Script DROP and CREATE" switch "Script CREATE" to "Script DROP" and press OK
Then, either save to file, clipboard, or new query window.
Run script.
Now, this will drop everything, including the database. Make sure to remove the code for the items you don't want dropped. Alternatively, in the "Choose Objects" section, instead of selecting to script entire database just select the items you want to remove.
The accepted answer doesn't support Azure. It uses an undocumented stored procedure "sp_MSforeachtable". If you get an "azure could not find stored procedure 'sp_msforeachtable" error when running or simply want to avoid relying on undocumented features (which can be removed or have their functionality changed at any point) then try the below.
This version ignores the entity framework migration history table "__MigrationHistory" and the "database_firewall_rules" which is an Azure table you will not have permission to delete.
Lightly tested on Azure. Do check to make this this has no undesired effects on your environment.
DECLARE #sql NVARCHAR(2000)
WHILE(EXISTS(SELECT 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'))
BEGIN
SELECT TOP 1 #sql=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
EXEC(#sql)
PRINT #sql
END
WHILE(EXISTS(SELECT * from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'))
BEGIN
SELECT TOP 1 #sql=('DROP TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'
EXEC(#sql)
PRINT #sql
END
Taken from:
https://edspencer.me.uk/2013/02/25/drop-all-tables-in-a-sql-server-database-azure-friendly/
http://www.sqlservercentral.com/blogs/sqlservertips/2011/10/11/remove-all-foreign-keys/
delete is used for deleting rows from a table. You should use drop table instead.
EXEC sp_msforeachtable 'drop table [?]'
/* Drop all Primary Key constraints */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
WHILE #name IS NOT NULL
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint is not null
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#name) +'] DROP CONSTRAINT [' + RTRIM(#constraint)+']'
EXEC (#SQL)
PRINT 'Dropped PK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
GO
/* Drop all tables */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP TABLE [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Table: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
END
GO
You are almost right, use instead:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DROP TABLE ?'
but second line you might need to execute more then once until you stop getting error:
Could not drop object 'dbo.table' because it is referenced by a FOREIGN KEY constraint.
Message:
Command(s) completed successfully.
means that all table were successfully deleted.
Short and sweet:
USE YOUR_DATABASE_NAME
-- Disable all referential integrity constraints
EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
-- Drop all PKs and FKs
declare #sql nvarchar(max)
SELECT #sql = STUFF((SELECT '; ' + 'ALTER TABLE ' + Table_Name +' drop constraint ' + Constraint_Name from Information_Schema.CONSTRAINT_TABLE_USAGE ORDER BY Constraint_Name FOR XML PATH('')),1,1,'')
EXECUTE (#sql)
GO
-- Drop all tables
EXEC sp_MSforeachtable 'DROP TABLE ?'
GO
Spot on!!
You can use below query to remove all the tables from database
EXEC sp_MSforeachtable #command1 = "DROP TABLE ?"
Happy coding !
Seems the command should be without the square blanket
EXEC sp_msforeachtable 'drop table ?'
The fasted way is:
New Database Diagrams
Add all table
Ctrl + A to select all
Right Click "Remove from Database"
Ctrl + S to save
Enjoy
For me, the easiest way:
--First delete all constraints
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'
ALTER TABLE ' + QUOTENAME(s.name) + N'.'
+ QUOTENAME(t.name) + N' DROP CONSTRAINT '
+ QUOTENAME(c.name) + ';'
FROM sys.objects AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN ('D','C','F','PK','UQ')
ORDER BY c.[type];
EXEC sys.sp_executesql #sql;
-- Then drop all tables
exec sp_MSforeachtable 'DROP TABLE ?'
Azure SQL + tables (with constraints) in a different schema than dbo + ipv6_database_firewall_rules condition.
This is a little extension for https://stackoverflow.com/a/43128914/4510954 answer.
DECLARE #sql NVARCHAR(2000)
WHILE(EXISTS(SELECT 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'))
BEGIN
SELECT TOP 1 #sql=('ALTER TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
EXEC(#sql)
PRINT #sql
END
WHILE(EXISTS(SELECT * from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules' AND TABLE_NAME != 'ipv6_database_firewall_rules'))
BEGIN
SELECT TOP 1 #sql=('DROP TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'
EXEC(#sql)
PRINT #sql
END
How about dropping the entire database and then creating it again? This works for me.
DROP DATABASE mydb;
CREATE DATABASE mydb;
For Temporal Tables it is a bit more complicated due to the fact there may be some foreign keys and also exception:
Drop table operation failed on table XXX because it is not a supported operation on system-versioned temporal tables
What you can use is:
-- Disable constraints (foreign keys)
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
-- Disable system versioning (temporial tables)
EXEC sp_MSForEachTable '
IF OBJECTPROPERTY(object_id(''?''), ''TableTemporalType'') = 2
ALTER TABLE ? SET (SYSTEM_VERSIONING = OFF)
'
GO
-- Removing tables
EXEC sp_MSForEachTable 'DROP TABLE ?'
GO
I know this is an old post now but I have tried all the answers on here on a multitude of databases and I have found they all work sometimes but not all of the time for various (I can only assume) quirks of SQL Server.
Eventually I came up with this. I have tested this everywhere (generally speaking) I can and it works (without any hidden store procedures).
For note mostly on SQL Server 2014. (but most of the other versions I tried it also seems to worked fine).
I have tried while loops and nulls etc etc, cursors and various other forms but they always seem to fail on some databases but not others for no obvious reason.
Getting a count and using that to iterate always seems to work on everything Ive tested.
USE [****YOUR_DATABASE****]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Drop all referential integrity constraints --
-- Drop all Primary Key constraints. --
DECLARE #sql NVARCHAR(296)
DECLARE #table_name VARCHAR(128)
DECLARE #constraint_name VARCHAR(128)
SET #constraint_name = ''
DECLARE #row_number INT
SELECT #row_number = Count(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
WHILE #row_number > 0
BEGIN
BEGIN
SELECT TOP 1 #table_name = tc2.TABLE_NAME, #constraint_name = rc1.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
AND rc1.CONSTRAINT_NAME > #constraint_name
ORDER BY rc1.CONSTRAINT_NAME
SELECT #sql = 'ALTER TABLE [dbo].[' + RTRIM(#table_name) +'] DROP CONSTRAINT [' + RTRIM(#constraint_name)+']'
EXEC (#sql)
PRINT 'Dropped Constraint: ' + #constraint_name + ' on ' + #table_name
SET #row_number = #row_number - 1
END
END
GO
-- Drop all tables --
DECLARE #sql NVARCHAR(156)
DECLARE #name VARCHAR(128)
SET #name = ''
DECLARE #row_number INT
SELECT #row_number = Count(*) FROM sysobjects WHERE [type] = 'U' AND category = 0
WHILE #row_number > 0
BEGIN
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
SELECT #sql = 'DROP TABLE [dbo].[' + RTRIM(#name) +']'
EXEC (#sql)
PRINT 'Dropped Table: ' + #name
SET #row_number = #row_number - 1
END
GO
sp_msforeachtable is not available in Azure SQL
For Azure SQL:
This query will drop Foreign Key constraints
DECLARE #Name VARCHAR(200)
DECLARE #Constraint VARCHAR(300)
DECLARE #SQL VARCHAR(300)
SELECT #Name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
WHILE #Name is not null
BEGIN
SELECT #Constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = #Name ORDER BY CONSTRAINT_NAME)
WHILE #Constraint IS NOT NULL
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#Name) +'] DROP CONSTRAINT [' + RTRIM(#Constraint) +']'
EXEC (#SQL)
PRINT 'Dropped FK Constraint: ' + #Constraint + ' on ' + #Name
SELECT #Constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> #Constraint AND TABLE_NAME = #Name ORDER BY CONSTRAINT_NAME)
END
SELECT #Name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
GO
This will drop all the tables from the database
DECLARE #Name VARCHAR(200)
DECLARE #SQL VARCHAR(300)
SELECT #Name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE #Name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP TABLE [dbo].[' + RTRIM(#name) +']' /*here you can change schema if it is different from dbo*/
EXEC (#SQL)
PRINT 'Dropped Table: ' + #Name
SELECT #Name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #Name ORDER BY [name])
END
GO
[This is a bit of an unusual problem, I know...]
What I need is a script that will change every unique id value to new one in our database. The problem is that we have configuration tables that can be exported between instances of our software which is id-sensitive (clobbering existing ids). Years ago, we set up a "wide-enough" id gap between our development "standard configuration" and our client's instances, which is now not wide enough :( - e.g. we're getting id conflicts when clients import our standard configuration.
A SQL script to do the following is definitely the simplest/shortest-timeframe thing that we can do. e.g. fixing the code is far too complicated and error prone to consider. Note that we are not "eliminating" the problem here. Just changing the gap from 1000's to 1000000's or more (the existing gap took 5 years to fill).
I believe the simplest solution would be to:
change all our tables to UPDATE_CASCADE (none of them are - this will greatly simplify the script)
create an identity table with the new lowest id that we want
For each table, modify the id to the next one in the identity table (using identity insert modifier flags where necessary). Perhaps after each table is processed, we could reset the identity table.
turn off UPDATE_CASCADE, and delete the identity table.
I am seeking any (partial or full) scripts for this.
Unfortunately UPDATE_CASCADE doesn't exist in the world of Sql Server. I suggest for each table you to re-key you do the following (Pseudo Code)
BACKUP DATABASE
CHECK BACKUP WORKS!
FOR EACH TABLE TO BE RE-KEYED
DROP ALL FOREIGN KEY CONSTRAINTS, INDEXES ETC FROM TABLE
SELECT ID + Number, ALL_OTHER_FIELDS INTO TEMP_TABLE FROM TABLE
RENAME TABLE OLD_TABLE
RENAME TEMP_TABLE TABLE
FOR ALL TABLES REFERENCING THIS TABLE
UPDATE FOREIGN_KEY_TABLE SET FK_ID = FK_ID + new number
END FOR
RE-APPLY FOREIGN KEY CONSTRAINTS, INDEXES ETC FROM TABLE
END FOR
Check it all still works ...
This process could be automated through DMO/SMO objects, but depending on the number of tables involved I'd say using management studio to generate scripts that can then be edited is probably quicker. After all, you only need to do this once/5 years.
Here we go with the code for SQL 2005. It's huge, it's hacky, but it will work (except in the case where you have a primary key that is a composite of two other primary keys).
If someone can re-write this with MrTelly's faster id addition (which wouldn't require building sql from a cursor for each updated row), then I'll mark that as the accepted answer. (If I don't notice the new answer, upvote this - then I'll notice :))
BEGIN TRAN
SET NOCOUNT ON;
DECLARE #newLowId INT
SET #newLowId = 1000000
DECLARE #sql VARCHAR(4000)
--**** SELECT ALL TABLES WITH IDENTITY COLUMNS ****
DECLARE tables SCROLL CURSOR
FOR
SELECT '[' + SCHEMA_NAME(schema_id) + '].[' + t.name + ']', c.name
FROM sys.identity_columns c
INNER JOIN sys.objects t
on c.object_id = t.object_id
WHERE t.type_Desc = 'USER_TABLE'
OPEN tables
DECLARE #Table VARCHAR(100)
DECLARE #IdColumn VARCHAR(100)
CREATE Table #IdTable(
id INT IDENTITY(1,1),
s CHAR(1)
)
FETCH FIRST FROM tables
INTO #Table, #IdColumn
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT('
****************** '+#Table+' ******************
')
--Reset the idtable to the 'low' id mark - remove this line if you want all records to have distinct ids across the database
DELETE FROM #IdTable
DBCC CHECKIDENT('#IdTable', RESEED, #newLowId)
--**** GENERATE COLUMN SQL (for inserts and deletes - updating identities is not allowed) ****
DECLARE tableColumns CURSOR FOR
SELECT column_name FROM information_schema.columns
WHERE '[' + table_schema + '].[' + table_name + ']' = #Table
AND column_name <> #IdColumn
OPEN tableColumns
DECLARE #columnName VARCHAR(100)
DECLARE #columns VARCHAR(4000)
SET #columns = ''
FETCH NEXT FROM tableColumns INTO #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #columns = #columns + #columnName
FETCH NEXT FROM tableColumns INTO #columnName
IF ##FETCH_STATUS = 0 SET #columns = #columns + ', '
END
CLOSE tableColumns
DEALLOCATE tableColumns
--**** GENERATE FOREIGN ROW UPDATE SQL ****
DECLARE foreignkeys SCROLL CURSOR
FOR
SELECT con.name,
'[' + SCHEMA_NAME(f.schema_id) + '].[' + f.name + ']' fTable, fc.column_name ,
'[' + SCHEMA_NAME(p.schema_id) + '].[' + p.name + ']' pTable, pc.column_name
FROM sys.foreign_keys con
INNER JOIN sysforeignkeys syscon
ON con.object_id = syscon.constid
INNER JOIN sys.objects f
ON con.parent_object_id = f.object_id
INNER JOIN information_schema.columns fc
ON fc.table_schema = SCHEMA_NAME(f.schema_id)
AND fc.table_name = f.name
AND fc.ordinal_position = syscon.fkey
INNER JOIN sys.objects p
ON con.referenced_object_id = p.object_id
INNER JOIN information_schema.columns pc
ON pc.table_schema = SCHEMA_NAME(p.schema_id)
AND pc.table_name = p.name
AND pc.ordinal_position = syscon.rkey
WHERE '[' + SCHEMA_NAME(p.schema_id) + '].[' + p.name + ']' = #Table
OPEN foreignkeys
DECLARE #FKeyName VARCHAR(100)
DECLARE #FTable VARCHAR(100)
DECLARE #FColumn VARCHAR(100)
DECLARE #PTable VARCHAR(100)
DECLARE #PColumn VARCHAR(100)
--**** RE-WRITE ALL IDS IN THE TABLE ****
SET #sql='DECLARE tablerows CURSOR FOR
SELECT CAST('+#IdColumn+' AS VARCHAR) FROM '+#Table+' ORDER BY '+#IdColumn
PRINT(#sql)
exec(#sql)
OPEN tablerows
DECLARE #rowid VARCHAR(100)
DECLARE #id VARCHAR(100)
FETCH NEXT FROM tablerows INTO #rowid
WHILE ##FETCH_STATUS = 0
BEGIN
--generate new id
INSERT INTO #IdTable VALUES ('')
SELECT #id = CAST(##IDENTITY AS VARCHAR)
IF #rowId <> #Id
BEGIN
PRINT('Modifying '+#Table+': changing '+#rowId+' to '+#id)
SET #sql='SET IDENTITY_INSERT ' + #Table + ' ON
INSERT INTO '+#Table+' ('+#IdColumn+','+#columns+') SELECT '+#id+','+#columns+' FROM '+#Table+' WHERE '+#IdColumn+'='+#rowId
--Updating all foreign rows...
FETCH FIRST FROM foreignkeys
INTO #FKeyName, #FTable, #FColumn, #PTable, #PColumn
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = #sql + '
UPDATE '+#FTable+' SET '+#FColumn+'='+#id+' WHERE '+#FColumn+' ='+#rowId
FETCH NEXT FROM foreignkeys
INTO #FKeyName, #FTable, #FColumn, #PTable, #PColumn
END
SET #sql=#sql + '
DELETE FROM '+#Table+' WHERE '+#IdColumn+'='+#rowId
PRINT(#sql)
exec(#sql)
END
FETCH NEXT FROM tablerows INTO #rowid
END
CLOSE tablerows
DEALLOCATE tablerows
CLOSE foreignkeys
DEALLOCATE foreignkeys
--Revert to normal identity operation - update the identity to the latest id...
DBCC CHECKIDENT(#Table, RESEED, ##IDENTITY)
SET #sql='SET IDENTITY_INSERT ' + #Table + ' OFF'
PRINT(#sql)
exec(#sql)
FETCH NEXT FROM tables
INTO #Table, #IdColumn
END
CLOSE tables
DEALLOCATE tables
DROP TABLE #IdTable
--COMMIT
--ROLLBACK
Why don't you use negative numbers for your standard configuration values and continue to use positive numbers for other things?
How can I drop all the default constraints belonging to a particular table in SQL 2005?
One solution from a search: (Edited for Default constraints)
SET NOCOUNT ON
DECLARE #constraintname SYSNAME, #objectid int,
#sqlcmd VARCHAR(1024)
DECLARE CONSTRAINTSCURSOR CURSOR FOR
SELECT NAME, object_id
FROM SYS.OBJECTS
WHERE TYPE = 'D' AND #objectid = OBJECT_ID('Mytable')
OPEN CONSTRAINTSCURSOR
FETCH NEXT FROM CONSTRAINTSCURSOR
INTO #constraintname, #objectid
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #sqlcmd = 'ALTER TABLE ' + OBJECT_NAME(#objectid) + ' DROP CONSTRAINT ' + #constraintname
EXEC( #sqlcmd)
FETCH NEXT FROM CONSTRAINTSCURSOR
INTO #constraintname, #objectid
END
CLOSE CONSTRAINTSCURSOR
DEALLOCATE CONSTRAINTSCURSOR
I know this is old, but I just found it when googling.
A solution that works for me in SQL 2008 (not sure about 2005) without resorting to cursors is below :
declare #sql nvarchar(max)
set #sql = ''
select #sql = #sql + 'alter table YourTable drop constraint ' + name + ';'
from sys.default_constraints
where parent_object_id = object_id('YourTable')
AND type = 'D'
exec sp_executesql #sql
Script posted by gbn does not work for me, so I'm using a modified version:
SET NOCOUNT ON
DECLARE #DfId INT, #TableId INT,
#SqlCmd VARCHAR(1024)
DECLARE DFCONSTRAINTCUR CURSOR FOR
SELECT [parent_object_id] TABLE_ID, [object_id] DF_ID
FROM SYS.OBJECTS
where parent_object_id = OBJECT_ID('<table name>')
and [TYPE] = 'D'
OPEN DFCONSTRAINTCUR
FETCH NEXT FROM DFCONSTRAINTCUR
INTO #TableId, #DfId
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #sqlcmd = 'ALTER TABLE ' + OBJECT_NAME(#TableId) + ' DROP CONSTRAINT ' + OBJECT_NAME(#DfId)
EXEC(#sqlcmd)
FETCH NEXT FROM DFCONSTRAINTCUR
INTO #TableId, #DfId
END
CLOSE DFCONSTRAINTCUR
DEALLOCATE DFCONSTRAINTCUR
Just why do you want to do this? Dropping constraints is a pretty drastic action and affects all users not just your process. Maybe your problem can be solved some other way. If you aren't the dba of the system, you should think very hard about whether you should do this. (Of course in most systems, a dba wouldn't allow anyone else the permissions to do such a thing.)