How to completely clean out a SQL Server 2005 database? - sql-server

I made a copy of a DB that is used for a web app to make a new instance of this web app. I am wondering how do I remove all data and transactions and what not so that it is just a clean empty shell of tables ready to be written with new data?

Sql Server Database Publishing Wizard. Create a script with just the schema, specifying to drop the existing objects.

run this script:
select 'TRUNCATE TABLE ' + name from sysobjects where xtype='U'
and then paste the results into a new script and run that
(And for God's sake, be careful!) :)
EDIT
From comments it seems TRUNCATE can't delete rows from tables with foreign keys.
You could use
select 'DELETE FROM ' + name from sysobjects where xtype='U'
and you would also have to rearrange the output to delete from child tables first. Others have suggested scripting a clean database and that is probably a better idea TBH.

Uncomment out the -- to actually run... BE CAREFUL!!
Declare #t varchar (1024)
Declare tbl_cur cursor for
select TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
OPEN tbl_cur
FETCH NEXT from tbl_cur INTO #t
WHILE ##FETCH_STATUS = 0
BEGIN
--EXEC ('TRUNCATE TABLE '+ #t)
FETCH NEXT from tbl_cur INTO #t
END
CLOSE tbl_cur
DEALLOCATE tbl_Cur
EDIT:
In answer to the comment question... damn good question. I imagine you could find all the foreign keys and save them off
SELECT 'ALTER TABLE ' + b.TABLE_NAME + ' WITH CHECK ADD CONSTRAINT [' + a.CONSTRAINT_NAME + '] FOREIGN KEY '
+ c.COLUMN_NAME + ' REFERENCES [' + d.TABLE_NAME +'] ([' + e.COLUMN_NAME + '])'
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS a
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS b
ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS d
ON a.UNIQUE_CONSTRAINT_NAME = d.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
ON a.CONSTRAINT_NAME = c.CONSTRAINT_NAME
INNER JOIN (
SELECT
f.TABLE_NAME,
g.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS f
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE g
ON f.CONSTRAINT_NAME = g.CONSTRAINT_NAME
WHERE f.CONSTRAINT_TYPE = 'PRIMARY KEY'
) e
ON e.TABLE_NAME = d.TABLE_NAME
ORDER BY a.CONSTRAINT_NAME
and then you could drop all of them (I dont believe it matters in which order you drop the constraints)
SELECT 'ALTER TABLE ' + col.TABLE_NAME + ' DROP CONSTRAINT ' + u.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.COLUMNS col
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE u
ON col.TABLE_NAME = u.TABLE_NAME
AND col.COLUMN_NAME = u.COLUMN_NAME
INNER JOIN INFORMATION_SCHEMA.table_constraints t
ON u.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.CONSTRAINT_TYPE = 'FOREIGN KEY'
and THEN use the first cursor to truncate all the tables. Then you can use the results of the script you saved off to recreate all of the FK relationships.

I don't know of any one step magical silver bullet command to do so, but if you want to preserve your tables/schemas, you'd probably need to script a truncate table for each.
Alternatively, you could script out the whole database and use that one script to regenerate a new database after you drop the "used" one. Making sense?
Right click on the Database you want to deal with, select Script Database As (3rd option from the top), then the option DROP and CREATE to ... at which point maybe you want to do this to a file or the clipboard and paste it somewhere.
Then, with this file handy as your script, run it to create a clean nice database.

You could create an empty database, and then use something like SQL Compare to compare your existing database against the empty one to generate scripts to recreate the database entirely from scratch.
You could also use the following SQL:
--// Switch to the database to be modified
USE DatabaseName;
--// The following commands need to be run for each table
--// You could perhaps automate this by using a cursor
--// First truncate the table and remove all data
TRUNCATE TABLE MyTable;
--// Also reset the identity seed
DBCC CHECKIDENT (MyTable, reseed, 1)
I'd recommend re-creating the database structure from scratch, rather than doing a backup-and-restore-to-new-database, as this will give you a completely clean database without any 'residue' (like stuff in the transaction log).

Truncating will work if you no foreign keys defined (And if you don't please please add them).
If your using SQL Server 2005 (08 might be the same), you can generate a script for the entire database, from within Sql Server Management Studio. Right click on the database you want to script.
Then go to tasks, and generate scripts. Script out all the objects, then you can use this script to build a fresh copy of the DB based on just the schema.

This article presents store-procedure without any of the mentioned problems.
The key is to disable referential integrity :)

You may want to consider just generating a t-sql script that only includes the structure from your existing database. The SQL Server Management Console makes this very easy, as you just need to right click on your original database, select 'tasks->generate scripts'. From there, just click through the defaults and select the objects that you want to duplicate (tables, etc).
This generates a nice T-SQL script that you can apply to any blank database, giving you the structure that you are looking for without the data. To me, this seems to be a more appropriate option as compared to truncation.

you would just truncate each table as in
use [dbname]
truncate table [table]
where [dbname] is the name of the copied database, and you would copy the 2nd line for each table in the database.
I'm sure with about 5-10 minutes, you could create a script that would read over all the available tables listed in the systables and use that information to do a while loop so you didn't have to write "truncate table [table]" for each table, but that's the general idea.
--
Ok,
To all that answered after me, I'm getting this mental "guilt" thing going on because I didn't write up that he should have created a TSQL script and re-create a database off of that.
There were several reasons why I didn't go that route.
You don't know what sorts of
"static" data he has in the
database.
He specifically asked
about how to clear the database.
I don't currently know what the #OP
has built into the rest of the
system. there could potentially be
dependencies that he needs a copy of
the original in order to satisfy a
condition.
Had the gentleman asked this in a different manner, I may have indeed answered like so many have and simply stated to script the database out.

Related

How can I remove tool generated columns named createdby updatedat etc

I used a Redgate tool to synchronize data from a SQL Server database, and in the process, the tool created four new columns in each table with names like createdby, updatedby, etc.
Now that the data is in sync, I don't want these columns anymore.
Is there a simple way, maybe a script, to remove these columns?
You can drop the columns by running the following statement
ALTER TABLE table_name
DROP COLUMN column_name;
https://www.sqlservertutorial.net/sql-server-basics/sql-server-alter-table-drop-column/
EDIT:
As Dale suggested, the intention might be to have a way to drop these columns en masse, so here's an update:
I tend to generate the code that does not have to be fully automated, but needs to be relatively easy to update. If I had dozens or hundreds of tables with extra columns that I want to remove, I would write a query similar to the one below, then copy the results from the lower pane in SSMS and execute the resulting script.
select 'alter table ' + quotename(table_schema) + '.' + quotename(table_name) + ' drop column ' + quotename(column_name)
from information_schema.columns
where 1=1
and column_name in ('createdby', 'updatedby')
Here is an alternative solution, not as good as #dalek
Suck the schema into Visual Studio using a new db project and tool-schema-compare. Then do replace all using the regex below, replace with nothing.
This removes the unwanted column
\[CreatedAt\][^\,.]+\,
this removes all the dangling commas at the end of a table column create that preceded the unwanted columns
\,([\s\r][\s]+)+\)

Exec tSQLt.Faketable crashing our original table constraint and data

During debugging the tsqlt code, I have directly run the below statement without wrapping it as sp and my original table constraint got deleted and some data missing from the original table.
Exec tSQLt.FakeTable #TableName = N'DBO.Employee', #Identity=1;
Exec tSQLt.FakeTable #TableName = N'DBO.Salary', #Identity=1;
How do I prevent running faketable statement in tsqlt is impacting the original table?
There is no way to prevent executing tSQLt.FakeTable outside of the framework. There are also good reasons to not prevent that, so I do not think that adding that functionality is the right approach.
However, if you’re using the newest version of tSQLt, you can use tSQLt.UndoTestDoubles to get the original object(s) back.
Ugh, been there... You can't prevent it, short of contributing to the project and putting a pull request in to add the functionality.
FakeTable creates a backup of your original table so you should be able to get the original table back. These backup table names start with tSQLt.tempobject and end in an identifier. You can delete the new "fake" table (which now has the name of your original table) and rename the tempobject table if/when you find it.
Something I've done in the past is to query for a column that I know is in the table to find the name of the tSQLt table:
SELECT t.name
FROM sys.columns c
INNER JOIN sys.tables t ON t.object_id = c.object_id
WHERE c.name = 'SomeCol';

How to delete all tables from db? Cannot delete from sys.tables

How can I perform this query on whatever way:
delete from sys.tables where is_ms_shipped = 0
What happened is, I executed a very large query and I forgot to put USE directive on top of it, now I got a zillion tables on my master db, and don't want to delete them one by one.
UPDATE: It's a brand new database, so I don't have to care about any previous data, the final result I want to achieve is to reset the master db to factory shipping.
If this is a one-time issue, use SQL Server Management Studio to delete the tables.
If you must run a script very, very carefully use this:
EXEC sp_msforeachtable 'DROP TABLE ?'
One method I've used in the past which is pretty simple and relatively foolproof is to query the system tables / info schema (depending on exact requirements) and have it output the list of commands I want to execute as the results set. Review that, copy & paste, run - quick & easy for a one-time job and because you're still manually hitting the button on the destructive bit, it's (IMHO) harder to trash stuff by mistake.
For example:
select 'drop table ' + name + ';', * from sys.tables where is_ms_shipped = 0
No backups? :-)
One approach may be to create a Database Project in Visual Studio with an initial Database Import. Then delete the tables and synchronize the project back to the database. You can do the deletes en masse with this approach while being "buffered" with a commit phase and UI.
I am fairly certain the above approach can be used to take care of the table relationships as well (although I have not tried in the "master" space). I would also recommend using a VS DB project (or other database management tool that allows schema comparing and synchronization) to make life easier in the future as well as allowing version-able (e.g. with SCM) schema change-tracking.
Oh, and whatever is done, please create a backup first. If nothing else, it is good training :-)
Simplest and shortest way I did was this:
How to Rebuild System Databases in SQL Server 2008
The problem with all other answers here is that it doesn't work, since there are related tables and it refuses to execute.
This one, not only it works but actually is what I am looking for: "Reset to factory defaults" as stated in the question.
Also this one will delete everything, not only tables.
This code could be better but I was trying to be cautious as I wrote it. I think it is easy to follow an easy to tweak for testing before you commit to deleting your tables.
DECLARE
#Prefix VARCHAR(50),
#TableName NVARCHAR(255),
#SQLToFire NVARCHAR(350)
SET #Prefix = 'upgrade_%'
WHILE EXISTS(
SELECT
name
FROM
sys.tables
WHERE
name like #Prefix
)
BEGIN
SELECT
TOP 1 --This query only iterates if you are dropping tables
#TableName = name
FROM
sys.tables
WHERE
name like #Prefix
SET #SQLToFire = 'DROP TABLE ' + #TableName
EXEC sp_executesql #SQLToFire;
END
I did something really similar, and what I wound up doing was using the Tasks--> script database to only script drops for all the database objects of the originally intended database. Meaning the database I was supposed to run the giant script on, which I did run it on. Be sure to include IF Exists in the advanced options, then run that script against the master and BAM, deletes everything that exists in the original target database that also exists in the master, leaving the differences, which should be the original master items.
Not very elegant but as this is a one time task.
WHILE EXISTS(SELECT * FROM sys.tables where is_ms_shipped = 0)
EXEC sp_MSforeachtable 'DROP TABLE ?'
Works fine on this simple test (clearing a on the second loop after failing on the first attempt and proceeding onwards to delete b)
create table a
(
a int primary key
)
go
create table b
(
a int references a (a)
)
insert into a values (1)
insert into b values (1)

Problem with multipart sql identifiers

I've successfully migrated a website running a SQL Server 2005 db to a new server running SQL Server 2008 R2 and everything seems to work fine except 1 thing.
2 different schemas where used when creating the tables (I have no idea why). So you have to call the tables using a multipart identifier like schemaname.tablename except in the websites sql code they call everything using either just tablename or schemaname.tablename which worked before but not now.
The website itself is a huge mess and would be extremely difficult to find and modify all the sql queries.
Does anyone know how I can change it so it allows queries with just tablename again?
One way to accomplish what you want is to have the different programs log in using different identities. You can then use ALTER USER or the SSMS UI to set the default schema of each user. The default schema specifies which schema is used when a user doesn't use a prefix.
Another thing to do, if you want to consolidate the schemas, would be to define synonyms for each object in the schema you want to get rid of, so you can eventually consolidate stuff down to one clean schema over time.
You can use ALTER SCHEMA to move securables between schemas in the same database.
This script will transfer tables, stored procedures and views in 'myschema' to 'dbo' schema. Modify to suit your needs and run this TSQL script:
SELECT 'ALTER SCHEMA dbo TRANSFER ' + s.Name + '.' + o.Name
FROM sys.objects o
INNER JOIN sys.schemas s on o.schema_id = s.schema_id
WHERE s.Name = 'myschema'
AND (o.Type = 'U' OR o.Type = 'P' OR o.Type = 'V')
and then copy the output to another query window and run. (Be careful, check everything is correct before moving)

If column exists query problem - SQL Server

I have a query to add a column if it doesn't exist. It works the first time, but if I run it again, it fails, saying that the column exists?!?
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TABLE_NAME' AND COLUMN_NAME = 'COLUMN_NAME')
BEGIN
ALTER TABLE TABLE_NAME ADD COLUMN nchar(3) NULL;
END
And when I run the query against INFORMATION_SCHEMA.COLUMNS, it returns nothing.
I've also tried the
IF NOT EXISTS (SELECT * FROM SYS.COLUMNS WHERE NAME = N'COLUMN_NAME' AND OBJECT_ID = OBJECT_ID(N'TABLE_NAME'))
version, which exhibits the same behavior (it works once, and fails on the second run).
At what point do the sys tables get updated, and what is the fool proof way to test if a column exists?
Thanks,
Sam
I believe it was a problem with USE due to our screwy database setup. The information_schema query was hitting master while the update targeted another database. D'oh!

Resources