Delete all indexes of specific database - sql

How to delete all indexes from one database, whether clustered or nonclustered?
I need do that with script, not over GUI.
EDITED
Database has 7 tables, some of them are lookups, some are related over foreign keys. Every table has minimal one index, created in time the primary key was created, so automatically was created constraint. When deleting such indexes over an GUI, I got an error that indexes cannot be deleted because of dependency on other keys.
So, I need to first delete an indexes keys that are foreign keys, and then an indexes created over primary keys.

Slightly different variation of dynamic SQL, however it drops foreign keys first, then primary keys, then indexes (non-clustered indexes first so that you don't convert to a heap (which can affect all the non-clustered indexes)).
USE specific_database;
GO
First, delete all foreign keys:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'ALTER TABLE '
+ QUOTENAME(OBJECT_SCHEMA_NAME([parent_object_id]))
+ '.' + QUOTENAME(OBJECT_NAME([parent_object_id]))
+ ' DROP CONSTRAINT ' + QUOTENAME(name) + ';
'
FROM sys.foreign_keys
WHERE OBJECTPROPERTY([parent_object_id], 'IsMsShipped') = 0;
EXEC sp_executesql #sql;
Now drop primary keys:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'ALTER TABLE '
+ QUOTENAME(OBJECT_SCHEMA_NAME([parent_object_id]))
+ '.' + QUOTENAME(OBJECT_NAME([parent_object_id]))
+ ' DROP CONSTRAINT ' + QUOTENAME(name) + ';
'
FROM sys.key_constraints
WHERE [type] = 'PK'
AND OBJECTPROPERTY([parent_object_id], 'IsMsShipped') = 0;
EXEC sp_executesql #sql;
And finally, indexes, non-clustered first:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'DROP INDEX '
+ QUOTENAME(name) + ' ON '
+ QUOTENAME(OBJECT_SCHEMA_NAME([object_id]))
+ '.' + QUOTENAME(OBJECT_NAME([object_id])) + ';
'
FROM sys.indexes
WHERE index_id > 0
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0
ORDER BY [object_id], index_id DESC;
EXEC sp_executesql #sql;
Note that the database engine tuning advisor will recommend a bunch of these indexes (and depending on the workload you present it, may miss some, and may suggest redundant and nearly duplicate indexes). However it is not going to recommend any of the data integrity stuff you just deleted (PK, FK, unique constraints).

create a Dynamic SQL
DECLARE #qry nvarchar(max);
SELECT #qry = (SELECT 'DROP INDEX ' + ix.name + ' ON ' + OBJECT_NAME(ID) + '; '
FROM sysindexes ix
WHERE ix.Name IS NOT NULL AND
ix.Name LIKE '%prefix_%'
FOR XML PATH(''));
EXEC sp_executesql #qry
Drop All Indexes and Stats in one Script

Related

Convert multiple int primary keys from different tables into Identity

I have a dozen or so different databases with similar structure, with around 50 different tables each, and some of these tables used a sequential int [Id] as Primary Key and Identity.
At some point, these databases were migrated to a different remote infrastructure, namely from Azure to AWS, and somewhere in the process, the Identity property was lost, and as such, new automated inserts are not working as it fails to auto-increment the Id and generate a valid primary key.
I've tried multiple solutions, but am struggling to get any of them to work, as SQL-Server seems extremely finicky with letting you mess with or alter value of Identity columns in any way, and it's driving me insane.
I need to re-enable the Identity in multiple different tables, in multiple databases, but the solutions I've found so far are either extremely convoluted or impractical, for what seems to be a relatively simple problem.
tl;dr - How can I enable Identity for all my int primary keys in multiple different tables at the same time?
My approach so far:
CREATE PROC Fix_Identity #tableName varchar(50)
AS
BEGIN
IF NOT EXISTS(SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = #tableName)
BEGIN
DECLARE #keyName varchar(100) = 'PK_dbo.' + #tableName;
DECLARE #reName varchar(100) = #tableName + '.Id_new';
EXEC ('Alter Table ' + #tableName + ' DROP CONSTRAINT ['+ #keyName +']');
EXEC ('Alter Table ' + #tableName + ' ADD Id_new INT IDENTITY(1, 1) PRIMARY KEY');
EXEC ('SET IDENTITY_INSERT [dbo].[' + #tableName + '] ON');
EXEC ('UPDATE ' + #tableName + ' SET [Id_new] = [Id]');
EXEC ('SET IDENTITY_INSERT [dbo].[' + #tableName + '] OFF');
EXEC ('Alter Table ' + #tableName + ' DROP COLUMN Id');
EXEC sp_rename #reName, 'Id', 'Column';
END
END;
I tried creating this procedure, to be executed once per table, but i'm having problems with the UPDATE statement, which I require to guarantee that the new values Identity column will have the same value as the old Id column, but this approach currently doesn't work because:
Cannot update identity column 'Id_new'.
There are assumptions made in that script that you might want to look out for specifically with assuming the PK constraint name. You might want to double check that on all of your tables before. The rest of your script seemed to make sense to me except you will need to reseed the index after updating the data in the new column.
See if this helps:
select t.name AS [Table],c.Name AS [Non-Indent PK],i.name AS [PK Constraint]
from sys.columns c
inner join sys.tables t On c.object_id=t.object_id
inner join sys.indexes i ON i.object_id=c.object_id
AND i.is_primary_key = 1
INNER JOIN sys.index_columns ic ON i.object_id=ic.object_id
AND i.index_id = ic.index_id
AND ic.column_id=c.column_id
WHERE c.Is_Identity=0
Instead of adding an identity, create a sequence and default constraint
declare #table nvarchar(50) = N'dbo.T'
declare #sql nvarchar(max) = (N'select #maxID = max(Id) FROM ' + #table);
declare #maxID int
exec sp_executesql #sql, N'#maxID int output', #maxID=#maxID OUTPUT;
set #sql = concat('create sequence ', #table, '_sequence start with ', #maxID + 1, ' increment by 1')
exec(#sql)
set #sql = concat('alter table ', #table, ' add default(next value for ', #table, '_sequence) for ID ')
exec(#sql)

SQL Server : change PK type from uniqueidentifier to int

I have designed a database that has primary key type uniqueidentifier for all tables. It has 50 tables and existing data. Then, I knew it was a bad idea. I want to change to int pk type from uniqueidentifier.
How can I do? How do I move the foreign key?
The general steps to take are (links are to MSDN information on performing these steps with SQL Server):
Delete the current Primary Key constraint - Delete Primary Key
Alter the table to drop your Unique Identifier field and create a new Integer field - Alter Table
Create a new Primary Key on the new Integer Field Create Primary Key
just done a script, tested on a couple of tables and works fine, test it yourself before you execute it in your production environment.
The Script does the following.
Find all the columns where Primary key has data type Uniqueidentifier.
Drop the primary key constraint.
drop the Uniqueidentifier column.
Add INT column with Identity starting with seed value of 1 and increment of 1.
Make that column the Primary key column in that table.
declare #table SYSNAME,#Schema SYSNAME
, #PkColumn SYSNAME, #ContName SYSNAME
,#Sql nvarchar(max)
DECLARE db_cursor CURSOR LOCAL FORWARD_ONLY FOR
SELECT OBJECT_NAME(O.object_id) AS ConstraintName
,SCHEMA_NAME(O.schema_id) AS SchemaName
,OBJECT_NAME(O.parent_object_id) AS TableName
,c.name ColumName
FROM sys.objects o
inner join sys.columns c ON o.parent_object_id = c.object_id
inner join sys.types t ON c.user_type_id = t.user_type_id
WHERE o.type_desc = 'PRIMARY_KEY_CONSTRAINT'
and t.name = 'uniqueidentifier'
Open db_cursor
fetch next from db_cursor into #ContName , #Schema , #table, #PkColumn
while (##FETCH_STATUS = 0)
BEGIN
SET #Sql= 'ALTER TABLE ' + QUOTENAME(#Schema) +'.'+ QUOTENAME(#table)
+ ' DROP CONSTRAINT ' + QUOTENAME(#ContName)
Exec sp_executesql #Sql
SET #Sql= 'ALTER TABLE ' + QUOTENAME(#Schema) +'.'+ QUOTENAME(#table)
+ ' DROP COLUMN ' + QUOTENAME(#PkColumn)
Exec sp_executesql #Sql
SET #Sql= 'ALTER TABLE ' + QUOTENAME(#Schema) +'.'+ QUOTENAME(#table)
+ ' ADD ' + QUOTENAME(#PkColumn)
+ ' INT NOT NULL IDENTITY(1,1) '
Exec sp_executesql #Sql
SET #Sql= 'ALTER TABLE ' + QUOTENAME(#Schema) +'.'+ QUOTENAME(#table)
+ ' ADD CONSTRAINT '+ QUOTENAME(#table+'_'+ #PkColumn)
+ ' PRIMARY KEY ('+QUOTENAME(#PkColumn)+')'
Exec sp_executesql #Sql
fetch next from db_cursor into #ContName , #Schema , #table, #PkColumn
END
Close db_cursor
deallocate db_cursor

Drop All User-Defined Types from SQL Server

I need to drop all User-Defined Types, User-Defined Data Types and User-Defined Tables (all in Types folder). Is it possible to do this using a T-SQL script, or must I use SSMS?
select 'drop type ' + quotename(schema_name(schema_id)) + '.' + quotename(name)
from sys.types
where is_user_defined = 1
You can try getting all you user defined type objects and create a script using this query or Generate Script Clicking Task under your database.
http://blog.falafel.com/t-sql-drop-all-objects-in-a-sql-server-database/
For the above link posted
T-SQL: Drop All Objects in a SQL Server Database
I added following code to replace check Constraint from Drop Constraint by Stefan Steiger to Drop All Constraints. I chose below code because it uses same approach
DECLARE #sql nvarchar(MAX)
SET #sql = ''
SELECT #sql = #sql + 'ALTER TABLE ' + QUOTENAME(RC.CONSTRAINT_SCHEMA)
+ '.' + QUOTENAME(KCU1.TABLE_NAME)
+ ' DROP CONSTRAINT ' + QUOTENAME(rc.CONSTRAINT_NAME) + '; '
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU1
ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG
AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
Declare #sql NVARCHAR(MAX) = N'';
SELECT #sql = #sql + N' DROP type '
+ QUOTENAME(SCHEMA_NAME(schema_id))
+ N'.' + QUOTENAME(name)
FROM sys.types
WHERE is_user_defined = 1
Exec sp_executesql #sql

Moving table from one database to another with primary key and other keys

I want to move all the table from one database to another with primary key and all other keys
using SQL queries. I am using SQL Server 2005 and I got a SQL queries to move the table but the keys are not moved.
And my queries is as follows
set #cSQL='Select Name from SRCDB.sys.tables where Type=''U'''
Insert into #TempTable
exec (#cSQL)
while((select count(tName) from #t1Table)>0)
begin
select top 1 #cName=tName from #t1Table
set #cSQL='Select * into NEWDB.dbo.'+#cName+' from SRCDB.dbo.'+#cName +' where 1=2'
exec(#cSQL)
delete from #t1Table where tName=#cName
end
where SRCDB is the name of source database and NEWDB is the name of destination database
How can I achieve this..?
Can anyone help me in this...
Thank you...
The following T-SQL statement move all the table, primary key and foreign key from one database to another. Notice that the method SELECT * INTO FROM ... WHERE 1 = 2 does not create COMPUTED columns and user-data types. Suppose also that all primary keys are clustered
--ROLLBACK
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #dsql nvarchar(max) = N''
SELECT #dsql += ' SELECT * INTO NEWDB.dbo.' + name + ' FROM SRCDB.dbo. ' + name + ' WHERE 1 = 2'
FROM sys.tables
--PRINT #dsql
EXEC sp_executesql #dsql
SET #dsql = N''
;WITH cte AS
(SELECT 1 AS orderForExec, table_name, column_name, constraint_name, ordinal_position,
'PRIMARY KEY' AS defConst, NULL AS refTable, NULL AS refCol
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1
UNION ALL
SELECT 2, t3.table_name, t3.column_name, t1.constraint_name, t3.ordinal_position,
'FOREIGN KEY', t2.table_name, t2.column_name
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as t1
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE t2 ON t1 .UNIQUE_CONSTRAINT_NAME = t2.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE t3 ON t1.CONSTRAINT_NAME = t3.CONSTRAINT_NAME
AND t3.ordinal_position = t2.ordinal_position
)
SELECT #dsql += ' ALTER TABLE NEWDB.dbo.' + c1.table_name +
' ADD CONSTRAINT ' + c1.constraint_name + ' ' + c1.defConst + ' (' +
STUFF((SELECT ',' + c2.column_name
FROM cte c2
WHERE c2.constraint_name = c1.constraint_name
ORDER BY c2.ordinal_position ASC
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(max)'), 1, 1, '') + ')' +
CASE WHEN defConst = 'FOREIGN KEY' THEN ' REFERENCES ' + c1.refTable + ' (' +
STUFF((SELECT ',' + c2.refCol
FROM cte c2
WHERE c2.constraint_name = c1.constraint_name
ORDER BY c2.ordinal_position ASC
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(max)'), 1, 1, '') + ')' ELSE '' END
FROM (SELECT DISTINCT orderForExec, table_name, defConst, constraint_name, refTable FROM cte) AS c1
ORDER BY orderForExec
--PRINT #dsql
EXEC sp_executesql #dsql
COMMIT TRAN
You can generate customized script of Source Database and run the script for Destination Database.
Here is the link and slightly better [one][2]
Get the complete table and then perform the delete queries on Destination database as per requirement
If you want to do with Query. I guess this link would be helpful
DECLARE #strSQL NVARCHAR(MAX)
DECLARE #Name VARCHAR(50)
SELECT Name into #TempTable FROM SRCDB.sys.tables WHERE Type='U'
WHILE((SELECT COUNT(Name) FROM #TempTable) > 0)
BEGIN
SELECT TOP 1 #Name = Name FROM #TempTable
SET #strSQL = 'SELECT * INTO NEWDB.dbo.[' + #Name + '] FROM SRCDB.dbo.[' + #Name + ']'
EXEC(#strSQL)
DELETE FROM #TempTable WHERE Name = #Name
END
DROP TABLE #TempTable
If you have destination table already created then just set identity insert on and change query like below :
SET #strSQL = ' SET IDENTITY_INSERT NEWDB.dbo.[' + #Name + '] ON; ' +
' INSERT INTO NEWDB.dbo.[' + #Name + '] SELECT * FROM SRCDB.dbo.[' + #Name + ']' +
' SET IDENTITY_INSERT NEWDB.dbo.[' + #Name + '] OFF '
UPDATE :
If you don't want records and only want to create table with all key constaints then check this solution :
In SQL Server, how do I generate a CREATE TABLE statement for a given table?
The following script copies many tables from a source DB into another destination DB, taking into account that some of these tables have auto-increment columns:
http://sqlhint.com/sqlserver/copy-tables-auto-increment-into-separate-database

How to drop a list of SQL Server tables, ignoring constraints?

I have a list of half a dozen MSSQL 2008 tables that I would like to remove at once from my database. The data has been entirely migrated to new tables. There is no reference in the new tables to the old tables.
The problem being that old tables comes with loads of inner FK constraints that have been autogenerated by a tool (aspnet_regsql actually). Hence dropping manually all constraints is a real pain.
How can I can drop the old tables ignoring all inner constraints?
It depends on how you want to drop the tables. If list of tables need to drop covers almost above 20 % of tables under your DB.
Then I will disable all the constraints in that DB under my script and drop the tables and Enable the constraints under the same script.
--To Disable a Constraint at DB level
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
--Write the code to DROP tables
DROP TABLE TABLENAME
DROP TABLE TABLENAME
DROP TABLE TABLENAME
--To Enable a Constraint at DB level
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
Finally to check the Status of your constraints fire up this Query.
--Checks the Status of Constraints
SELECT (CASE
WHEN OBJECTPROPERTY(CONSTID, 'CNSTISDISABLED') = 0 THEN 'ENABLED'
ELSE 'DISABLED'
END) AS STATUS,
OBJECT_NAME(CONSTID) AS CONSTRAINT_NAME,
OBJECT_NAME(FKEYID) AS TABLE_NAME,
COL_NAME(FKEYID, FKEY) AS COLUMN_NAME,
OBJECT_NAME(RKEYID) AS REFERENCED_TABLE_NAME,
COL_NAME(RKEYID, RKEY) AS REFERENCED_COLUMN_NAME
FROM SYSFOREIGNKEYS
ORDER BY TABLE_NAME, CONSTRAINT_NAME,REFERENCED_TABLE_NAME, KEYNO
If you dont want to disable the constraints at Database level then make a list of tables which you want to drop.
Step1 : Check the Constraints associated with thos tables
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('dbo.Tablename')
Step2 : Disable the Constraints which are associated with these tables.
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint
Step3 : Drop the tables
DROP TABLE TABLENAME
A simple DROP TABLE dbo.MyTable will ignore all constraints (and triggers) except foreign keys (unless you drop the child/referencing table first) where you may have to drop these first.
Edit: after comment:
There is no automatic way. You'll have to iterate through sys.foreign_keys and generate some ALTER TABLE statements.
Run the following script to delete all the constraints in all tables under current DB and then run the drop table statements.
DECLARE #dropAllConstraints NVARCHAR(MAX) = N'';
SELECT #dropAllConstraints += N'
ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(parent_object_id)) +
' DROP CONSTRAINT ' + QUOTENAME(name) + ';'
FROM sys.foreign_keys;
EXEC sp_executesql #dropAllConstraints
I found a reasonable(ish) way to do it by making SQL write the SQL to drop the constraints:
select concat("alter table ", table_name, " drop ", constraint_type ," ", constraint_name, ";")
from information_schema.table_constraints
where table_name like 'somefoo_%'
and
constraint_type <> "PRIMARY KEY";
You will want to modify the table name to suit your needs, or possibly select against other column/values.
Also, this would select any non primary key constraint, which might be too big of a sledgehammer. Maybe you need to just set it to =?
I am not a DBA. there may be better ways to do this, but it worked well enough for my purposes.
I finally found the solution based on the script provided by Jason Presley. This script automatically removes all constraints in the DB. It's easy to add a WHERE clause so that it only applies to the set of concerned tables. After that, dropping all tables is a straightforward.
Be very careful with the following script, all tables, views, functions, stored procedures and user defined types from a database ignoring all constraints.
/*
Description: This script will remove all tables, views, functions, stored procedures and user defined types from a database.
*/
declare #n char(1)
set #n = char(10)
declare #stmt nvarchar(max)
-- procedures
select #stmt = isnull( #stmt + #n, '' ) +
'drop procedure [' + schema_name(schema_id) + '].[' + name + ']'
from sys.procedures
-- check constraints
select #stmt = isnull( #stmt + #n, '' ) +
'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.check_constraints
-- functions
select #stmt = isnull( #stmt + #n, '' ) +
'drop function [' + schema_name(schema_id) + '].[' + name + ']'
from sys.objects
where type in ( 'FN', 'IF', 'TF' )
-- views
select #stmt = isnull( #stmt + #n, '' ) +
'drop view [' + schema_name(schema_id) + '].[' + name + ']'
from sys.views
-- foreign keys
select #stmt = isnull( #stmt + #n, '' ) +
'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.foreign_keys
-- tables
select #stmt = isnull( #stmt + #n, '' ) +
'drop table [' + schema_name(schema_id) + '].[' + name + ']'
from sys.tables
-- user defined types
select #stmt = isnull( #stmt + #n, '' ) +
'drop type [' + schema_name(schema_id) + '].[' + name + ']'
from sys.types
where is_user_defined = 1
exec sp_executesql #stmt
I suspect that you would have to do an 'alter' command on the offending tables before the drop to remove the forigen key contraints.
ALTER TABLE Orders DROP FOREIGN KEY fk_PerOrders;
DROP TABLE Orders;
Of course if you drop the child tables first, then you wont have this problem.
(unless you have table A contraint to table B and table B constraint to A, then you will need to Alter one of the tables, e.g. A to remove the constraint)
e.g. this WONT work, since Orders has a contraint from Order_Lines
DROP TABLE Orders;
DROP TABLE Order_lines;
e.g. this will work
DROP TABLE Order_lines;
DROP TABLE Orders;