Delete all tables in SQL Server database except few - sql

I have around 50+ table in my database now what I want is drop all the tables in database except few.
now what I know is sys.tables is a table that list all tables so initially I ran a query like this
delete from sys.tables where name like '%DynamicSurgery' (or any other condition)
thinking that it might work. But as I expected it throws an error as
Ad hoc updates to system catalogs are not allowed.
Please tell me if there is a way to delete multiples in SQL Server?

You can use dynamic query to DROP the required tables:
DECLARE #ExecSQL AS NVARCHAR (MAX) = '';
SELECT #ExecSQL = #ExecSQL +
'DROP TABLE ' + QUOTENAME(S.name) + '.' + QUOTENAME(T.name) + '; '
FROM sys.tables T
JOIN sys.schemas S ON S.schema_id = T.schema_id
WHERE T.name LIKE '%DynamicSurgery'
--PRINT #ExecSQL
EXEC (#ExecSQL)

EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL';
EXEC sp_MSforeachtable 'IF OBJECT_ID(''?'') NOT IN (
ISNULL(OBJECT_ID(''[dbo].[Table1]''),0),
ISNULL(OBJECT_ID(''[dbo].[Table2]''),0)
)
DELETE FROM ?';
EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL';

select the table by clicking on it
press the delete button and hit enter.
Take note : if there is any dependencies(Foreign Key), the table will not be deleted

Related

Drop all constraints from tables with a certain prefix

I'm trying to delete certain tables from my database that have a certain prefix using SQL Server 2014, these tables have constraints of course, so I looked for the equivalent of SET foreign_key_checks = 0 in MySQL and so far i tried this :
Attempt
Running
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
then drop all tables with this generated script :
SELECT 'drop table ' + table_name
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'myprefix%'
then
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
Result
Some tables were deleted, and some threw an error
... is referenced by a FOREIGN KEY constraint.
which is weird because I thought that the stored procedure I ran disabled them.
Is there a way to delete these constraints all-together? Since I have the scripts to create them again, is there a way I can delete the constraints from sys.foreign_keys but only from the tables that have the prefix?
Edit - Context
I was working in isolation on an existing module that's part of our huge web app, now it's time to include the changes I made and sync them with the dev database, I was asked to generate the scripts to update it for all the tables, views, stored procedures.. etc that I created.
So, instead of doing scripts that add columns to existing tables, I though it'd be much easier to just drop the tables, and then re-create them, data is not important here, it's all dummy data I used while testing.
Since you mentioned already having the scripts required to regenerate the foreign keys, here's a way to generate and execute the drops. You might want to add some error handling.
declare #sql varchar(max);
declare c cursor local fast_forward for
select concat
(
'alter table ',
quotename(s.name),
'.',
quotename(t.name),
' drop constraint ',
quotename(fk.name)
)
from sys.foreign_keys fk
join sys.tables t on t.object_id = fk.parent_object_id
join sys.schemas s on t.schema_id = s.schema_id
where t.is_ms_shipped = 0
and t.name like 'myprefix%';
open c;
fetch next from c into #sql;
while (##fetch_status = 0)
begin
print #sql;
--exec(#sql); uncomment after checking output and run again (or just run output manually)
fetch next from c into #sql;
end

Drop constraints not knowing its name

My problem.
I have a database and it is a big one, I want to remove a specific constraint between to table and i wanna do it with a migration scripts written in Visual Studio. I have it for development purposes running locally on my pc but it also runs on a staging server.
I could use the name of the constraint locally and it would work, but on the staging server the name is different. So thats why I want to do without knowing its name.
I've been reading a lot post here on stackoverflow regarding same issue but none of them works for me.
I've build a small databaseto try different code on before i try it on the big DB.
It looks like this:
I've tried this:
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Genres')
SELECT
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) +
'.[' + OBJECT_NAME(parent_object_id) +
'] DROP FOREIGN_KEY_CONSTRAINT ' + name
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Genres')
And this
DECLARE #SQL NVARCHAR(MAX) = N'';
SELECT #SQL += N'
ALTER TABLE ' + OBJECT_NAME(PARENT_OBJECT_ID) + ' DROP CONSTRAINT ' + OBJECT_NAME(OBJECT_ID) + ';'
FROM SYS.OBJECTS
WHERE TYPE_DESC LIKE '%CONSTRAINT' AND OBJECT_NAME(PARENT_OBJECT_ID) = 'Albums';
EXECUTE #SQL
In both cases it finds the constraint tries to drop it, but is still there.
It even prints out the name of the constraint i want to remove.

Drop all the tables without any Constraint Error in SQL SERVER 2008

I want to DROP all the tables with name starts with particular name, I wrote the script for the same but, when I try to delete the TABLE , I am getting Constraint issue.
So I want the approach to drop each table, in loop without/ignoring Relationships/Forieng_Key. Please suggested optimized script to perform the same operation. Please share your thoughts.
DECLARE #SqlStatement VARCHAR(MAX)
SET #SqlStatement = ''
Print 'Deleting Tables and Columns from the Agency Table schema'
SELECT #SqlStatement =
COALESCE(#SqlStatement, '') + 'DROP TABLE ['+#agencyName+'].' + QUOTENAME(TABLE_NAME) + ';' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = #agencyName;
PRINT #SqlStatement
--exec(#SqlStatement) -- In this Line I am getting the Foreign Key constraint issue. how do I achieve the functionality.
--DROP SCHEMA Agency3

How to create an alias of database in SQL Server

We have a very old software has been created around 10 years ago and we don't have source code.
The software uses two databases, DB01 and DB02 on the same SQL Server 2012 instance.
There is SQL statements such as db01..table1 join db02..table2, but the main issue is our processes don't allow us use db02 as a name of database.
The question is: how we can create an alias of for database?
I was trying to use CREATE SYNONYM
CREATE SYNONYM [db02] FOR [db02_new_name];
but it doesn't work for database names.
Please suggest how it can be solved without patching a binary files to correct SQL statements.
Create a database with the name you want to impersonate. Re-jigg the DDL code generator to create a view for every table in the database that has the tables I need to access via the hardcoded name. Basically, each view will have a statement that looks like this..
CREATE VIEW schemaname.tablename as SELECT * FROM targetdbname.schemaname.tablename
Example:
The target database name that is hardcoded is called ProdDBV1 and the Source DB you have is named ProductDatabaseDatabaseV1, schema is dbo and table name is customer
Create the database called ProdDBV1 using SSMS or script.
CREATE VIEW dbo.customer as SELECT * FROM ProductDatabaseDatabaseV1.dbo.customer
If you can enumerate each table in your "source" database and then create the DDL as above. If you want I can update this posting with a code example. (using the sp_msforeachtable procedure if possible)
I had a similar issue.
Solved with this workaround, using synonyms.
Short version: You flood your database with a synonym of every object you'll ever need to reference. Later you re-create every synonym with the other database name.
Here's a stored proc to do it. Simply add it to your database and call it with the target database. It will create synonyms for all tables in the target database, and create the schemas if they don't exist. I've left a commented out section in case someone knows of a way to get the create schemas working without a cursor.
CREATE PROCEDURE CreateSynonymsForTargetDatabase (
#databaseName sysname
)
AS BEGIN
DECLARE #TSQL nvarchar(max) = N''
DECLARE #rn char(2),
#SchemaName sysname;
SET #rn = char(13) + char(10)
CREATE TABLE #DBSynonym(
[Schema] sysname NOT NULL,
[Table] sysname NOT NULL
)
SET #TSQL = N'
INSERT INTO #DBSynonym ([Schema], [Table])
SELECT Schemas.name, Tables.name
FROM [' + #databaseName + '].sys.tables
INNER JOIN [' + #databaseName + '].sys.schemas on tables.schema_id = schemas.schema_id
'
EXEC (#TSQL)
SET #TSQL = N''
DECLARE MissingSchemasCursor CURSOR
READ_ONLY
FOR
SELECT newSchemas.[Schema]
FROM #DBSynonym newSchemas
LEFT JOIN sys.schemas on newSchemas.[Schema] = schemas.name
WHERE schemas.schema_id is null
GROUP BY newSchemas.[Schema]
OPEN MissingSchemasCursor
FETCH NEXT FROM MissingSchemasCursor INTO #SchemaName
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
SET #TSQL = N'CREATE SCHEMA ' + QUOTENAME(#SchemaName) + N';'
EXEC sp_executesql #TSQL
END
FETCH NEXT FROM MissingSchemasCursor INTO #SchemaName
END
CLOSE MissingSchemasCursor
DEALLOCATE MissingSchemasCursor
/*
SELECT #TSQL = #TSQL +
N'
GO
CREATE SCHEMA ' + QUOTENAME([Schema]) + N';'
FROM #DBSynonym newSchemas
LEFT JOIN sys.schemas on newSchemas.[Schema] = schemas.name
WHERE schemas.schema_id is null
GROUP BY newSchemas.[Schema]
PRINT 'CREATE SCHEMAS : ' + ISNULL(#TSQL,'')
EXEC sp_executesql #TSQL
*/
SET #TSQL = N''
SELECT #TSQL = #TSQL +
N'
CREATE SYNONYM ' + QUOTENAME([Schema]) + N'.' + QUOTENAME([Table]) + N'
FOR ' + QUOTENAME(#databaseName) + N'.' + QUOTENAME([Schema]) + N'.' + QUOTENAME([Table]) + N';'
FROM #DBSynonym
EXEC sp_executesql #TSQL
SET #TSQL = N''
END
GO
Use it as follows :
EXEC CreateSynonymsForTargetDatabase 'targetDbName'
The question is: how we can create an alias of for database?
I know this is an old post but...
This is why I only use the 2 part naming convention for SQL objects. It allows me to have 2 part synonyms that point to differently named databases depending on what environment I'm in. There are some places where it doesn't work so well but, for the most part, those places are very rare.
As for software that you don't have the source code of and if that software uses the 3 part naming convention, you're probably just out of luck unless you know what the 3 part naming convention is for each object and create a 3 part synonym for each object.
I found Charles' answer (and the linked workaround in the comment by maxcastaneda) very useful. I followed this approach and it works for me. I have streamlined it a bit and created the following query that brings up all required synonyms to create.
As a prerequisite for this snippet both the original DB and the synonym/alias db have to be on the same server otherwise in case you use linked server or so you have to modify it a bit.
It should be fairly easy to put this into a small sp to update the synonyms automatically.
USE <SYNONYMDB>
SELECT
'[' + TABLE_NAME + ']',
'[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']',
'IF EXISTS (SELECT * FROM sys.synonyms WHERE name = ''' + TABLE_NAME + ''') DROP SYNONYM ['+ TABLE_NAME + ']; CREATE SYNONYM [' + TABLE_NAME + '] FOR <ORIGINALDB>.' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']' AS SynonymUpdateScript FROM <ORIGINALDB>.INFORMATION_SCHEMA.TABLES
Don't forget to enter you Db names at the <...> spots.
Just copy the content of the SynonymUpdateScript Column and execute it in the synonym DB - or create a stored procedure for this task.
Be aware there is an issue if you have views in place that refer to tables or other db objects without the 2 part naming convention. Those synonyms won't work. You should fix this in the original objects / views.
Go to the Database you wish to create Alias,
Create an Alias Folders table with the preferred design,
Go to unique IDs's table and check the last code sequence for the table created.
For example, if the last code is 10, then update it to 11.
Open Cabinets table and go right at the bottom and create the name of the Alias cabinet you want.
You can create an alias from 'SQL Server Configuration Manager' under Configuartion Tool in SQL Server Folder.
Detailed source : http://www.mssqltips.com/sqlservertip/1620/how-to-setup-and-use-a-sql-server-alias/
http://technet.microsoft.com/en-us/library/ms190445.aspx

Is there a simpler and faster way of dropping a table that has foreign key references to other tables?

I have a new table that has foreign key references to a number of existing tables. When I create the new table for the first time, I created the foreign keys in the following way:
ALTER TABLE [dbo].[NewTable] WITH CHECK ADD FOREIGN KEY([SectionDatabaseID])
REFERENCES [dbo].[Section] ([SectionDatabaseID])
ALTER TABLE [dbo].[NewTable] WITH CHECK ADD FOREIGN KEY([TermDatabaseID])
REFERENCES [dbo].[Term] ([TermDatabaseID])
The above way will generate names for the foreign key constraints using it's own automated naming convention.
However, I want to drop the new table because I need to do some major modifications by creating it from scratch.
Obviously, if I just execute a drop statement, the SQL Server database will complain stating that the new table has foreign key references to other tables.
I've heard of running the following script to figure out what foreign keys exist so that we can drop them:
use perls;
SELECT 'ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME +
'] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']'
FROM information_schema.table_constraints
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' and TABLE_NAME = 'NewTable'
The above will give results that basically show alter statements which I need to run.
I need something more automated. Why do I have to drop each foreign key constraint separately, and then only be able to drop the table?
I want to drop the table in a simpler way. It's got to be easier than what I need to do above.
Relational databases are designed to enforce database integrity. Your statements are potentially destroying constraints that were carefully added to protect the data quality. Automating the dropping of integrity constraints from a production database could be a disaster for a company. So when the SQL language was developed, making it easy to drop tables that are referenced by other tables was not high on the priority of important tasks. With a database engine for enterprise data, the product is designed more for DBAs than for casual users.
What is the reason for wanting to drop multiple tables that are being referenced in foreign keys? Can you be sure that you are not going to be destroying somebody else's queries?
Assuming that you are working on a non critical system, your approach of writing a script to write a drop script is about the best solution that I know of.
Yes you must drop the FKs first. I've ran into this before and have written just the script you need to automate the task. Replace DBName and TABLENAME below.
Warning to all: This script will drop a specific table (or group of tables) as well as all FK constraints! Use with caution, and always take a db backup before doing a major operation like this.
use DBName
/*
SCRIPT TO DROP TABLES WITH FK'S, INDEXES
https://mellodev.snipt.net/drop-tables-with-fk-contraints/
*/
set nocount on
declare #tables table (tablename varchar(255));
insert into #tables
select name from sys.tables where name in
('TABLENAME')
-- Iterate tables, drop FK constraints and tables
declare #tablename varchar(255);
declare cTable cursor for
select tablename from #tables
open cTable
fetch next from cTable into #tableName
while ##FETCH_STATUS=0
begin
-- Identify any FK constraints
declare #fkCount int;
SELECT #fkCount = COUNT(*)
FROM sys.foreign_keys
WHERE referenced_object_id = object_id(#tablename)
-- Drop any FK constraints from the table
if (#fkCount>0) begin
declare #dropFkSql nvarchar(max);set #dropFkSql='';
declare #fkName nvarchar(max);
declare cDropFk cursor for
SELECT 'ALTER TABLE [' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT [' + name + ']',name
FROM sys.foreign_keys
WHERE referenced_object_id = object_id(#tablename)
open cDropFk
fetch next from cDropFk into #dropfksql,#fkName
while ##FETCH_STATUS=0
begin
exec sp_executesql #dropFkSql;
select 'Dropped FK Constraint: ' + #fkName
fetch next from cDropFk into #dropfksql,#fkName
end
close cDropFk
deallocate cDropFk
end
-- Drop the table
declare #dropTableSql nvarchar(max);
set #dropTableSql='DROP TABLE [' + #tablename + ']';
exec sp_executesql #dropTableSql;
select 'Dropped table: ' + #tablename
fetch next from cTable into #tableName
end
close cTable
deallocate cTable
If you are using MSSQL then you can use this script that i wrote to purge the whole DB from data without dropping the tables themselves.
use [MyDataBase]
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL';
select tbl.* into dbo.DeleteQueries from (SELECT 'DELETE ' + name + ';' as query
FROM sys.tables
WHERE name <> 'DeleteQueries') as tbl
Declare #query nvarchar(100)
While (Select Count(*) From dbo.DeleteQueries Where query <> '') > 0
Begin
Select Top 1 #query = query From dbo.DeleteQueries Where query <> ''
exec(#query);
Update dbo.DeleteQueries Set query = '' Where query = #query
End
DROP TABLE dbo.DeleteQueries
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
you can add tables that you don't want to purge in the where clause of the "select into" query.
Hope this helps