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]+)+\)
Related
Unable to update the column_name column in information_schema.columns
I have a table named 'knd' in MS-SQL server. Now I want to alter the column names of all the columns in this table in this way:
for example, my column names in this table are: Fuel category, fuel type, end date, start date
I want to update these names to [Fuel category], [fuel type], [end date], [start date]. i.e column names must include [] and the updation should be done in one shot.
What I have tried:
update INFORMATION_SCHEMA.COLUMNS
Set COLUMN_NAME = CONCAT('[',COLUMN_NAME,']')
where TABLE_NAME = 'knd'
I get the below error:
Ad hoc updates to system catalogs are not allowed.
I tried to reconfigure with override as below, but didn't work:
exec sp_configure 'allow updates','1';
go
reconfigure with override
go
even if I have to use exec sp_rename, how can I do it for all columns in one shot. I believe using sp_rename requires more manual intervention as my column names might change tommorow .
Can someone please help to accomplish this?
First: This is a terrible idea, as everyone wrote in the comments. Adding square brackets to column names will only force you to refer to the columns with double square brackets - to refer to a column named [fuel type] you will have to write [[fuel type]]].
Second, You can't directly update system tables or the views that relies on them. Everything in the sys schema and in the INFORMATION_SCHEMA schema is readonly. To rename a column in a view, you must write an alter view statement, or use sp_rename. To rename a column in a table, you must write an alter table statement or use sp_rename.
That being said, it's best to first find all objects that depends on the column you want to rename, becuase renaming a column will not rename every reference to it, so you might break stuff when renaming.
You can query the built in table valued function sys.dm_sql_referencing_entities to get dependencies of an object in SQL Server.
Quotename does the needful in my case as suggested by #jeroen-mostert in one of the above comments!!.
Below is my simple code snippet to perform this for all the columns in my table set.
Select STUFF((SELECT N',' + QUOTENAME(C.COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_NAME = 'knd'
FOR XML PATH(N''),TYPE).value(N'.',N'nvarchar(MAX)'),1,1,N'')
Result is as follows:
[Start Date_(MM-DD-YYYY)],[End Date_(MM-DD-YYYY)],[mode],[scac],[fuel category],[Fuel Type],[Base],[Escalator],[Surcharge],[FSC # $3.2],[Step],[Co_ID]
WHAT I EXPECT:
I want to create a Job in my SQL Server Agent that allows me to fire off a stored procedure to clean up a particular table. The spu would take two parameters: TableName and Days.
TableName would be the name of the table I'm looking for and Days would be how far back I wish to delete records.
WHAT I'VE DONE:
After having looked around online I've found sources on how to see if a User Database holds the supplied TableName:
SELECT *
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME = #TableName
This results in a few rows looking a bit like this:
TABLE_CATALOG | TABLE_SCHEMA |TABLE_NAME |TABLE_TYPE
Database_A | table_schema |table_A |table_type
WHAT I DON'T UNDERSTAND:
How can I use the resulting rows of the previous query to find all rows of the supplied #TableName in a particular Database? In pseudo:
SELECT * FROM table_A WHERE database = database_A
I know I need to use a cursor somehow, that's not the problem.
What I'm simply struggling to understand is how I can use the database name and the table name to find the rows of the table in a particular database.
In my case I've got 10 or so databases that need to be iterated through to find the initial dataset (all user databases where #TableName exists) and then a secondary query to find all rows of the #TableName in the database that the cursor currently is pointing at.
You have to do select * from ..table_A
but you can't do that in a a simple TSQL. Possibly you could generate a sub script and execute.
SO,
I am trying to find a (messy?) solution to an even more messy problem. I have a SQL Server 2014 database which, in part, stores data from another software package but also stores data for me. The software creates a table with specific fields for each set of data - a Name and a Geometry field. For example, one might contain cities (dtCitiesData), another contains roads (dtRoadsData), another contains states(dtStates), etc. I also have a table (dtSpatialDataTables) which stores the names of the tables which store the data I want. That table only has 2 fields: ID and TableName.
I would like to create a SELECT statement which queries dtSpatialDataTables for all entries, then queries all tables with the name corresponding to each TableName result, and SELECTs Name and Geometry from them.
In pseudocode, effectively I want to do this:
SELECT TableName FROM dtSpatialDataTables
FOREACH TableName :
SELECT Name, Geometry FROM (TableName)
I can do this easily PHP via a first query against dtSpatialDataTables and then a loop of queries to each of the returned row TableNames but I want to know if this is possible via SQL directly.
In reality, what I want to do is create a VIEW with this query so I can directly query the VIEW rather than soak of processing time on potentially lots of queries.
Is this possible? Unfortunately, my Google-ing doesn't turn up any meaningful results.
Thanks everyone!
PS: I figure this is messy and not the way this should be done. But I have no choice in how the software puts data in my database. I simply have to use what I get. So... whether this is the "right" way or the "wrong" way, I need a solution. :)
you could do something like this using dynamic sql..
CREATE PROCEDURE dbo.usp_SpatialData_GetByID
(
#ID INT
)
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX),
#Selects NVARCHAR(MAX) = 'SELECT Name, Geometry, ''<<TableName>>'' AS Source FROM <<TableName>>'
SELECT #SQL = COALESCE(#SQL + ' UNION ALL ', '') + REPLACE(#Selects, '<<TableName>>', TableName)
FROM dtSpatialDataTables
WHERE ID = #ID
EXEC(#SQL)
END
GO
I feel like you left out filtering of the Geometry tables somewhere so you might have to add a filter to the #Selects statement
Can this be done in bulk too? So that all columns in the table can be set to switch off the 'NOT NULL' flag?
You should be able to use an ALTER TABLE xxx ALTER COLUMN statement to redefine the column.
If this is a one-time thing you need to run, you could use a trick by writing a query that queries the column names for the table from the system/dba table and generates your alter statements. You copy the results of the query (your 15 or however many alter statements) into your script and just run that. I don't have much mssql experience nor an environment to test on right now but something along the lines of:
SELECT
'ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name + ' ' + data_type
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_NAME = 'xxx'
where you will need to manipulate the data_type part to add/remove the NULL constraint text
To do it in bulk, once...
Use SSMS designer to generate a script. This will rebuild your table (create a temp table, copy data, drop old table, rename temp table).
Otherwise, it's one at a time using ALTER TABLE...
Yes, you can do it. Read books online.
No, it can't be done in bulk, but you could execute several statements in a single query.
Get a list of the columns and a template that has the required SQL and use some tool to create the statements for you.
I have done this in Excel before, but you could write a real program using your language of choice.
When the number of tables is low enough I'm using SSMSE (SQL Server Management Studio Express), by entering design mode on each table and checking Allow Nulls on the required columns.
For a larger number of tables, try the answer provided by ChrisCM.
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.