Execute Dynamically Selected Query in SQL - sql

I am using a Multi tenant Shared schema database, so i have so many schema,
Required:
I want to remove some schema; for that i have to remove all the CONSTRAINT of tables in that schema to delete a table. I got the the list of query to remove all the CONSTRAINT of a schema and the query to delete the tables from below code
Question:
From the below code i got a list of Queries,now i am copy that queries and executing that list of queries manually,can i do that automatically ?
Code
SET NOCOUNT ON;
DECLARE #SchemaName nvarchar(250)
SET #SchemaName='schemaname1'
--Step 1: Remove all CONSTRAINT
SELECT 'ALTER TABLE ' +'[' + s.name + '].[' + t.name + ']' +' DROP CONSTRAINT [' + f.name +']'
FROM sys.foreign_keys f
INNER JOIN sys.TABLES t ON f.parent_object_id=t.object_id
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0
and t.schema_id = schema_id(#SchemaName);
--Step 2: Drop all Tables
SELECT 'DROP TABLE ' + '[' + s.name + '].[' + t.name + ']'
FROM sys.TABLES t
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0 and t.schema_id = schema_id(#SchemaName);

Using COALESCE function we can turn multiple rows into a single string in SQL Server
Following code is working fine, to delete All the table in a Schema
SELECT * INTO #mytemp FROM INFORMATION_SCHEMA.SCHEMATA
WHERE [SCHEMA_NAME] in ('schemaname1','schemaname2','schemaname3')
WHILE (SELECT Count(*) FROM #mytemp) > 0
BEGIN
DECLARE #SCHEMA_NAME varchar(100)
SELECT #SCHEMA_NAME = [SCHEMA_NAME] FROM #mytemp
DECLARE #SQL VARCHAR(MAX)
SET #SQL='';
--Step 1: Remove all CONSTRAINT
SELECT #SQL= COALESCE(#SQL,'') +'ALTER TABLE ' +'[' + s.name + '].[' + t.name + ']' +' DROP CONSTRAINT [' + f.name +']'+ ' ; '
FROM sys.foreign_keys f
INNER JOIN sys.TABLES t ON f.parent_object_id=t.object_id
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0
and t.schema_id = schema_id(#SCHEMA_NAME);
--Step 2: Drop all Tables
SELECT #SQL= COALESCE(#SQL,'')+'DROP TABLE ' + '[' + s.name + '].[' + t.name + ']'+ ' ; '
FROM sys.TABLES t
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0 and t.schema_id = schema_id(#SCHEMA_NAME);
EXEC(#SQL)
--Custom Query End
DELETE #mytemp WHERE [SCHEMA_NAME] = #SCHEMA_NAME
END
DROP TABLE #mytemp

Related

T-SQL :: TRUNCATE or DELETE all tables in schema

I need to TRUNCATE or DELETE all tables in schema.
I found this code:
-- disable all constraints
EXEC sp_MSForEachTable #command1='ALTER TABLE ? NOCHECK CONSTRAINT all',#whereand='and Schema_Id=Schema_id(''Person'')'
-- delete data in all tables
Exec Sp_msforeachtable #command1='Truncate Table ?',#whereand='and Schema_Id=Schema_id(''Person'')'
-- enable all constraints
exec sp_MSForEachTable #command1='ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all',#whereand='and Schema_Id=Schema_id(''Person'')'
-- if some of the tables have identity columns we may want to reseed them
EXEC sp_MSForEachTable #command1='DBCC CHECKIDENT ( ''?'', RESEED, 0)',#whereand='and Schema_Id=Schema_id(''Person'')'
but on AdventureWorks it gives me:
Cannot truncate table 'Person.Address' because it is being referenced by a FOREIGN KEY constraint.
So I found this alternative code:
DECLARE #STRSQL NVARCHAR(MAX);
DECLARE #TABLE NVARCHAR(128);
DECLARE #SCHEMA_NAME VARCHAR(50)
SET #SCHEMA_NAME = 'Person'
SET #STRSQL = '';
DECLARE #C1 CURSOR SET #C1 = CURSOR
FOR
SELECT TOP 2 TABLE_SCHEMA + '.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = #SCHEMA_NAME
OPEN #C1
FETCH NEXT
FROM #C1
INTO #TABLE
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #TABLE
SET #STRSQL = #STRSQL + 'DELETE FROM ' + #TABLE + ';'
FETCH NEXT
FROM #C1
INTO #TABLE
END
CLOSE #C1
DEALLOCATE #C1
PRINT #STRSQL
EXEC sp_executesql #STRSQL
But the result is the same:
Person.Address
Person.AddressType
DELETE FROM Person.Address;DELETE FROM Person.AddressType;
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_BusinessEntityAddress_Address_AddressID". The conflict occurred in database "AdventureWorks2014", table "Person.BusinessEntityAddress", column 'AddressID'.
The statement has been terminated.
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_BusinessEntityAddress_AddressType_AddressTypeID". The conflict occurred in database "AdventureWorks2014", table "Person.BusinessEntityAddress", column 'AddressTypeID'.
The statement has been terminated.
How to TRUNCATE or DELETE all tables in schema?
You simply need to wrap your "delete from all the tables" script with a "drop all foreign keys" script at the beginning, and "re-create all foreign keys" script at the end. I show one way to do that here:
Drop and Re-Create All Foreign Key Constraints in SQL Server
However, I would argue that it is much cleaner to just script out the database and empty objects from source control than spend all this time and effort deleting data from one table at a time.
Anyway an attempt at what you're doing (if you truncate you don't also need to checkident, I'm not sure I would ever use undocumented and unsupported procedures like sp_msforeachtable, and I also stay the heck away from INFORMATION_SCHEMA). Please try this on a test database.
CREATE TABLE #x -- feel free to use a permanent table
(
drop_script nvarchar(max),
create_script nvarchar(max)
);
DECLARE #drop nvarchar(max) = N'',
#create nvarchar(max) = N'';
-- drop is easy, just build a simple concatenated list from sys.foreign_keys:
SELECT #drop += N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name)
+ ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS ct
ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs
ON ct.[schema_id] = cs.[schema_id];
INSERT #x(drop_script) SELECT #drop;
-- create is a little more complex. We need to generate the list of
-- columns on both sides of the constraint, even though in most cases
-- there is only one column.
SELECT #create += N'
ALTER TABLE '
+ QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name)
+ ' ADD CONSTRAINT ' + QUOTENAME(fk.name)
+ ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
-- get all the columns in the constraint table
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.parent_column_id = c.column_id
AND fkc.parent_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(N''), TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
+ ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
+ '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
-- get all the referenced columns
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.referenced_column_id = c.column_id
AND fkc.referenced_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(N''), TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs
ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs
ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;
UPDATE #x SET create_script = #create;
PRINT #drop;
PRINT #create;
EXEC sys.sp_executesql #drop
-- clear out data etc. here
DECLARE #truncate nvarchar(max) = N'';
SELECT #truncate += N'TRUNCATE TABLE ' + QUOTENAME(s.name)
+ N'.' + QUOTENAME(t.name) + N';'
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.[schema_id] = t.[schema_id];
EXEC sys.sp_executesql #truncate;
EXEC sys.sp_executesql #create;
Notes:
this is untested. As ludly as I can: try this on a test database.
this was meant to execute exactly once, so I don't drop the #temp table (it may be useful to keep it alive long enough to troubleshoot if things go south)
PRINT is not necessarily going to show you the full command that is going to be executed, so it's not a valid way to determine if the script is correct. It is just meant as a quick eyeball. If you really want to view the whole command, you'll need something a little more elaborate.
this doesn't handle indexed views, and I'm sure there are other limitations that might prevent you from truncating some tables (I'm thinking temporal or always encrypted with enclaves or in-mem), but I would resolve those separately and keep truncate around instead of "fixing" that by using a much more log-intensive delete.
Thank you #AaronBertrand, I forked your awesome query to make a more suitable one for what I need to do:
SELECT cs.name AS SchemaName
,ct.name AS TableName
,rt.name AS ColumnName
,fk.name AS ForeignKeyName
,fk.object_id AS ObjectID
,fk.parent_object_id AS ParentObjectID
,
-- drop constraint
N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';' AS Drop_Constraint_Script
,
-- create constraint
N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) + ' ADD CONSTRAINT ' + QUOTENAME(fk.name) + ' FOREIGN KEY (' + STUFF((
SELECT ',' + QUOTENAME(c.name)
-- get all the columns in the constraint table
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc ON fkc.parent_column_id = c.column_id
AND fkc.parent_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(N'')
,TYPE
).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name) + '(' + STUFF((
SELECT ',' + QUOTENAME(c.name)
-- get all the referenced columns
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc ON fkc.referenced_column_id = c.column_id
AND fkc.referenced_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(N'')
,TYPE
).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');' AS Create_Constraint_Script
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0
AND ct.is_ms_shipped = 0
ORDER BY 1
,2
,3

Programmatically rename all system name constraints

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

Drop default constraint in SQL Server on many columns

For SQL Server 2008 R2 I want to remove default constraints for date columns that allow null and the constraint contains 1899. And I want a script that can tested and then executed in live. I don't wan't to fiddle with this in live environment. Another reason for a script is that there is several databases with the same scheme
With help from Google I have the following script that list columns
SELECT tables.name, all_columns.name, all_columns.is_nullable, default_constraints.name, default_constraints.definition
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
schemas.name = 'dbo'
and default_constraints.definition like '%1899%'
and all_columns.is_nullable = 1
order by tables.name, all_columns.name, default_constraints.name
Now this list over hundred columns. The next script do what I want for the column CargoPool.Created. But how can I iterate all rows created from my first script ?
DECLARE #tableName VARCHAR(MAX) = 'CargoPool'
DECLARE #columnName VARCHAR(MAX) = 'Created'
DECLARE #ConstraintName nvarchar(200)
SELECT #ConstraintName = Name
FROM SYS.DEFAULT_CONSTRAINTS
WHERE PARENT_OBJECT_ID = OBJECT_ID(#tableName)
AND PARENT_COLUMN_ID = (
SELECT column_id FROM sys.columns
WHERE NAME = #columnName AND object_id = OBJECT_ID(#tableName))
IF #ConstraintName IS NOT NULL
EXEC('ALTER TABLE '+#tableName+' DROP CONSTRAINT ' + #ConstraintName)
If you want to drop all the constraints from your first query, you can build up a dynamic SQL with the results of that query and then execute it:
DECLARE #sql AS NVARCHAR(MAX) = N''
SELECT #sql = #sql + N'ALTER TABLE '
+ QUOTENAME(schemas.name) + N'.' + QUOTENAME(tables.name)
+ N' DROP CONSTRAINT ' + QUOTENAME(default_constraints.name) + N'; '
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
schemas.name = N'dbo'
and default_constraints.definition like N'%1899%'
and all_columns.is_nullable = 1
order by tables.name, all_columns.name, default_constraints.name
exec sp_executesql #sql;

How do I get constraints on a SQL Server table column

I have a column called MealType (VARCHAR) in my table with a CHECK constraint for {"Veg", "NonVeg", "Vegan"}
That'll take care of insertion.
I'd like to display these options for selection, but I couldn't figure out the SQL query to find out the constraints of a particular column in a table.
From a first glance at system tables in SQL Server, it seems like I'll need to use SQL Server's API to get the info. I was hoping for a SQL query itself to get it.
Easiest and quickest way is to use:
sp_help 'TableName'
This query should show you all the constraints on a table:
select chk.definition
from sys.check_constraints chk
inner join sys.columns col
on chk.parent_object_id = col.object_id
inner join sys.tables st
on chk.parent_object_id = st.object_id
where
st.name = 'Tablename'
and col.column_id = chk.parent_column_id
can replace the select statement with this:
select substring(chk.Definition,2,3),substring(chk.Definition,9,6),substring(chk.Definition,20,5)
SELECT obj_table.NAME AS 'table',
columns.NAME AS 'column',
obj_Constraint.NAME AS 'constraint',
obj_Constraint.type AS 'type'
FROM sys.objects obj_table
JOIN sys.objects obj_Constraint
ON obj_table.object_id = obj_Constraint.parent_object_id
JOIN sys.sysconstraints constraints
ON constraints.constid = obj_Constraint.object_id
JOIN sys.columns columns
ON columns.object_id = obj_table.object_id
AND columns.column_id = constraints.colid
WHERE obj_table.NAME='table_name'
ORDER BY 'table'
You can use
sp_helpconstraint 'tableName', 'nomsg'
to get all the constraints for the table.
"sp_help" return far more information.
Thanks to orgtrigger for his example!
I improved it to be able to remove unnecessary constraints (and then create their modified versions, if needed). Maybe this code will be useful for anybody.
-- removing old constraints
DECLARE #ConstraintNames TABLE (Name VARCHAR(MAX), RowNum INT)
DECLARE #TableName VARCHAR(100) = 'HubSpot'
INSERT #ConstraintNames
SELECT [constraint].name,
ROW_NUMBER() OVER (ORDER BY [constraint].[name]) AS RowNum
FROM sys.default_constraints [constraint]
INNER JOIN sys.columns col
ON [constraint].parent_object_id = col.object_id
INNER JOIN sys.tables st
ON [constraint].parent_object_id = st.object_id
WHERE
st.name = #TableName
AND col.name IN ('ForceUpdateOnImport', 'ForceUpdateOnExport')
AND col.column_id = [constraint].parent_column_id
SELECT * FROM #ConstraintNames
DECLARE #i INT = 1,
#count INT,
#constraintName VARCHAR(MAX),
#sql VARCHAR(MAX)
SELECT #count = COUNT(1) FROM #ConstraintNames
WHILE #i <= #count
BEGIN
SELECT #constraintName = cn.Name FROM #ConstraintNames cn WHERE cn.RowNum = #i
SET #sql = 'ALTER TABLE ' + #TableName + ' DROP CONSTRAINT ' + #constraintName
EXEC (#sql)
SET #i = #i + 1
END
Below is helpful for check and default constraints. I use it for implicit constraints to offer up guidance for what the name should be. If you remove everything after the where clause, it should be good for any check/default constraints.
SELECT /* obj_table.NAME AS 'table',
columns.NAME AS 'column',
obj_Constraint.NAME AS 'constraint',
obj_Constraint.type AS 'type',
sss.name as 'schema',*/
'ALTER TABLE [' + ltrim(rtrim(sss.name))+'].['+ltrim(rtrim(obj_table.name)) + '] DROP CONSTRAINT [' + obj_Constraint.NAME + '];' As 'Wrong_Implicit_Constraint',
'ALTER TABLE [' + ltrim(rtrim(sss.name))+'].['+ltrim(rtrim(obj_table.name)) + '] ADD CONSTRAINT [' + CASE obj_Constraint.type
WHEN 'D' THEN 'DF' WHEN 'F' THEN 'FK'
WHEN 'U' THEN 'UX' WHEN 'PK' THEN 'PK' WHEN 'N' THEN 'NN' WHEN 'C' THEN 'CK'
END + '_' + ltrim(rtrim(obj_table.name)) + '_' + columns.NAME + ']' +
CASE obj_Constraint.type WHEN 'D' THEN ' DEFAULT (' + dc.definition +') FOR [' + columns.NAME + ']'
WHEN 'C' THEN ' CHECK (' + cc.definition +')'
ELSE '' END +
';' As 'Right_Explicit_Constraint'
FROM sys.objects obj_table
JOIN sys.objects obj_Constraint ON obj_table.object_id = obj_Constraint.parent_object_id
JOIN sys.sysconstraints constraints ON constraints.constid = obj_Constraint.object_id
JOIN sys.columns columns ON columns.object_id = obj_table.object_id
AND columns.column_id = constraints.colid
left join sys.schemas sss on obj_Constraint.schema_id=sss.schema_id
left join sys.default_constraints dc on dc.object_id = obj_Constraint.object_id
left join sys.check_constraints cc on cc.object_id = obj_Constraint.object_id
WHERE obj_Constraint.type_desc LIKE '%CONSTRAINT'
AND RIGHT(obj_Constraint.name,10) LIKE '[_][_]________' --match double underscore + 8 chars of anything
AND RIGHT(obj_Constraint.name,8) LIKE '%[A-Z]%' --Ensure alpha in last 8
AND RIGHT(obj_Constraint.name,8) LIKE '%[0-9]%' --Ensure numeric in last 8
AND RIGHT(obj_Constraint.name,8) not LIKE '%[^0-9A-Z]%' --Ensure no special chars

How can I drop all indexes in a SQL database with one command?

So, how can I drop all indexes in a SQL database with one command? I have this command that will get me all the 20 or so drop statements, but how can I run all of those drop statements from this "result set"?
select * from vw_drop_idnex;
Another variation that gives me the same list is:
SELECT 'DROP INDEX ' + ix.Name + ' ON ' + OBJECT_NAME(ID) AS QUERYLIST
FROM sysindexes ix
WHERE ix.Name IS NOT null and ix.Name like '%pre_%'
I tried to do "exec(select cmd from vw_drop_idnex)" and it didn't work. I am looking for something that works like a for loop and runs the queries one by one.
-----------------------
With Rob Farleys help, final draft of the script is:
declare #ltr nvarchar(1024);
SELECT #ltr = ( select 'alter table '+o.name+' drop constraint '+i.name+';'
from sys.indexes i join sys.objects o on i.object_id=o.object_id
where o.type<>'S' and is_primary_key=1
FOR xml path('') );
exec sp_executesql #ltr;
declare #qry nvarchar(1024);
select #qry = (select 'drop index '+o.name+'.'+i.name+';'
from sys.indexes i join sys.objects o on i.object_id=o.object_id
where o.type<>'S' and is_primary_key<>1 and index_id>0
for xml path(''));
exec sp_executesql #qry
You're very close.
declare #qry nvarchar(max);
select #qry =
(SELECT 'DROP INDEX ' + quotename(ix.name) + ' ON ' + quotename(object_schema_name(object_id)) + '.' + quotename(OBJECT_NAME(object_id)) + '; '
FROM sys.indexes ix
WHERE ix.Name IS NOT null and ix.Name like '%prefix_%'
for xml path(''));
exec sp_executesql #qry
this worked for me
we skip sys indexes and for constraints
declare #qry nvarchar(max);
select #qry = (
select 'IF EXISTS(SELECT * FROM sys.indexes WHERE name='''+ i.name +''' AND object_id = OBJECT_ID(''['+s.name+'].['+o.name+']'')) drop index ['+i.name+'] ON ['+s.name+'].['+o.name+']; '
from sys.indexes i
inner join sys.objects o on i.object_id=o.object_id
inner join sys.schemas s on o.schema_id = s.schema_id
where o.type<>'S' and is_primary_key<>1 and index_id>0
and s.name!='sys' and s.name!='sys' and is_unique_constraint=0
for xml path(''));
exec sp_executesql #qry
From: Stephen Hill's Bloggie
DECLARE #indexName VARCHAR(128)
DECLARE #tableName VARCHAR(128)
DECLARE [indexes] CURSOR FOR
SELECT [sysindexes].[name] AS [Index],
[sysobjects].[name] AS [Table]
FROM [sysindexes]
INNER JOIN [sysobjects]
ON [sysindexes].[id] = [sysobjects].[id]
WHERE [sysindexes].[name] IS NOT NULL
AND [sysobjects].[type] = 'U'
--AND [sysindexes].[indid] > 1
OPEN [indexes]
FETCH NEXT FROM [indexes] INTO #indexName, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
--PRINT 'DROP INDEX [' + #indexName + '] ON [' + #tableName + ']'
Exec ('DROP INDEX [' + #indexName + '] ON [' + #tableName + ']')
FETCH NEXT FROM [indexes] INTO #indexName, #tableName
END
CLOSE [indexes]
DEALLOCATE [indexes]
GO
None of the answers quite suited my needs.
I needed one that will also drop indexes that backup unique or primary constraints (except if these can't be dropped as they back up a foreign key)
DECLARE #SqlScript NVARCHAR(MAX);
SELECT #SqlScript =
(
SELECT
'
BEGIN TRY
'+ CASE WHEN 1 IN (i.is_primary_key, i.is_unique_constraint) THEN
'
ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name) + ' DROP CONSTRAINT ' + QUOTENAME(i.name) + ';'
else
'
DROP INDEX ' + QUOTENAME(i.name) + ' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name)
END+'
END TRY
BEGIN CATCH
RAISERROR(''Could not drop %s on table %s'', 0,1, ' + QUOTENAME(i.name, '''') + ', ' + QUOTENAME(t.name, '''') + ')
END CATCH
'
FROM sys.indexes i
JOIN sys.tables t ON i.object_id = t.object_id
WHERE i.type_desc IN ('CLUSTERED', 'NONCLUSTERED' )
ORDER BY t.object_id, i.index_id DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)');
--Return script that will be run
SELECT #SqlScript AS [processing-instruction(x)]
FOR XML PATH('');
EXEC (#SqlScript);
Minor improvements to the accepted answer that I had to make in my own case, mostly to account for schemas:
declare #qry nvarchar(4000);
select #qry = (select 'drop index ['+s.name+'].['+o.name+'].['+i.name+'];'
from sys.indexes i join sys.objects o on i.object_id=o.object_id join sys.schemas s on o.schema_id=s.schema_id
where o.type<>'S' and is_primary_key<>1 and index_id>0 and s.name<>'sys'
for xml path(''));
exec sp_executesql #qry
Also: In my case it couldn't run in one go because the script becomes longer than 4000 characters. The only way I could think of to deal with that was to put a "top 20" on the inner select and execute it multiple times.
The "Final Draft" that OP posts as part of his question errors out if there are already zero indexes on any table in the DB. I needed to fix that.
Also, I wanted more control over the process than dropping all indexes on all tables, so I wrote the following stored proc to do it one table at a time:
CREATE PROCEDURE [dbo].[sp_DropAllIndexesOnTable]
#TableName varchar(1000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #DropCommand1 nvarchar(4000)
DECLARE #DropCommand2 nvarchar(4000)
--Create Temp Table to hold the names and table names of all Clustered Indexes
SELECT o.name AS TableName, i.name AS IndexName
INTO #AllClustered
FROM sys.indexes i
INNER JOIN sys.objects o ON i.object_id=o.object_id
WHERE o.type <> 'S'
AND is_primary_key = 1
--Create Temp Table to hold the names and table names of all NonClustered Indexes
SELECT o.name AS TableName, i.name AS IndexName
INTO #AllNonClustered
FROM sys.indexes i
INNER JOIN sys.objects o ON i.object_id=o.object_id
WHERE o.type <> 'S'
AND is_primary_key <> 1
AND index_id > 0
--Create DROP CONSTRAINT command for the Primary Key Constraint if there is one
SELECT #DropCommand1 = ( SELECT 'ALTER TABLE dbo.['+ TableName +'] DROP CONSTRAINT ['+ IndexName +'];'
FROM #AllClustered
WHERE TableName = #TableName
FOR xml path('') );
--Create DROP INDEX command for the indexes on the table if there are any
SELECT #DropCommand2 = ( SELECT 'DROP INDEX [' + IndexName + '] ON dbo.['+ TableName +'];'
FROM #AllNonClustered
WHERE TableName = #TableName
FOR xml path('') );
IF (#DropCommand1 IS NULL AND #DropCommand2 IS NULL) PRINT 'No action taken, zero indexes found on table ' + #TableName
IF #DropCommand1 IS NOT NULL EXEC sp_executesql #DropCommand1
IF #DropCommand2 IS NOT NULL EXEC sp_executesql #DropCommand2
DROP TABLE IF EXISTS #AllClustered
DROP TABLE IF EXISTS #AllNonClustered
END
GO
I cycle through the specific tables in my DB which I want to drop indexes on using a loop, and I drop the indexes by calling this proc with the table name, and recreate better ones right after. This way, only one table at a time has no indexes.
The reason I do this and the number of tables I do it on would make your head spin, but I definitely needed a proc like this!
SELECT 'DROP INDEX [' + IX.NAME + '] ON ' + OBJECT_NAME(IX.OBJECT_ID) + '; '
FROM SYS.INDEXES IX
JOIN SYS.OBJECTS O ON IX.OBJECT_ID = O.OBJECT_ID
INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE
IX.NAME IS NOT NULL
AND O.TYPE <> 'S'
AND IS_PRIMARY_KEY <> 1
AND INDEX_ID > 0
AND S.NAME != 'SYS' AND S.NAME!= 'SYS' AND IS_UNIQUE_CONSTRAINT = 0
Modify conditions according to your needs
If u want to delete PK constraints, you will get this message if you try to drop index:
An explicit DROP INDEX is not allowed on index... It is being used for PRIMARY KEY constraint enforcement.
Then, use this...
SELECT 'ALTER TABLE [' + O.NAME + '] DROP CONSTRAINT ' + IX.NAME + '; '
FROM SYS.INDEXES IX
JOIN SYS.OBJECTS O ON IX.OBJECT_ID = O.OBJECT_ID
INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE
IX.NAME IS NOT NULL
AND O.TYPE <> 'S'
AND INDEX_ID > 0
AND S.NAME != 'SYS' AND S.NAME!= 'SYS'