Add one common column in whole database - sql

I need add one common column in whole database tables.Any shortcuts or query or scripts to add the one column in whole database. because near 100 tables are there in that database .Please suggest me any ideas to add columns in all tables

You can generate all queries, and then execute them:
SELECT concat('ALTER TABLE ',TABLE_NAME,' add column mycolumnname mytype;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'yourschema';

You can use a prepared statement by using the ? operator instead of the table name.
here is the code:
ALTER TABLE ?
ADD column_name column-definition;

There's a very similar question here:
Add a column if it doesn't exist to all tables?
And yes, you can also generate a script from a query as #Kobi suggested.
SELECT
'IF NOT EXISTS(SELECT * FROM sys.columns c WHERE c.[name] = ''COLUMN_NAME'' AND c.[object_id] = OBJECT_ID(N''[' + SCHEMA_NAME(t.schema_id) + '].[' + t.[name] + ']'', N''U''))
ALTER TABLE [' + SCHEMA_NAME(t.schema_id) + '].[' + t.[name] + ']
ADD COLUMN_NAME INT NULL
'
FROM sys.tables t

Related

How to attach [dbo] prefix to table name when selecting all tables from a given database?

I'm performing the query which is listed below the question using SSMS or directly C# code. As a result, I get a table with a list of names all available tables in this database.
In majority of cases these table names can be used directly in all kind of 'SELECT' queries. However, if the current database is AdventureWorks2017, then all table names are corrupted. In case if I want to perform any 'SELECT' query, I have to manually add all prefixes which are not [dbo] (like, for example, [HumanResources], [Person], etc).
Also, my question is: what kind of query should I use in order to get the full prefixed table name (like [AdventureWorks2017].[HumanResources].[Employee] or [Northwind].[dbo].[CustomerCustomerDemo])?
use 'someDBName'
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = 'someDBName'
SELECT '[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']' AS SchemaAndTable
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_CATALOG = 'DbName'
FWIW, the table names are not corrupted, they're just in a different schema than the usual (default) one of dbo
To get the database name as well you'd do this:
SELECT '[' + TABLE_CATALOG + '].[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']' AS DbSchemaAndTable
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_CATALOG = 'DbName'

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.

Delete all tables in SQL Server database except few

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

SQL Server 2008: create trigger across all tables in db

Using SQL Server 2008, I've created a database where every table has a datetime column called "CreatedDt". What I'd like to do is create a trigger for each table so that when a value is inserted, the CreatedDt column is populated with the current date and time.
If you'll pardon my pseudocode, what I'm after is the T-SQL equivalent of:
foreach (Table in MyDatabase)
{
create trigger CreatedDtTrigger
{
on insert createddt = datetime.now;
}
}
If anyone would care to help out, I'd greatly appreciate it. Thanks!
As #EricZ says, the best thing to do is bind a default for the column. Here's how you'd add it to every table using a cursor and dynamic SQL:
Sure, You can do it with a cursor:
declare #table sysname, #cmd nvarchar(max)
declare c cursor for
select name from sys.tables where is_ms_shipped = 0 order by name
open c; fetch next from c into #table
while ##fetch_status = 0
begin
set #cmd = 'ALTER TABLE ' + #table + ' ADD CONSTRAINT DF_' + #table + '_CreateDt DEFAULT GETDATE() FOR CreateDt'
exec sp_executesql #cmd
fetch next from c into #table
end
close c; deallocate c
No need to go for Cursors. Just copy the result of below Query and Execute.
select distinct 'ALTER TABLE '+ t.name +
' ADD CONSTRAINT DF_'+t.name+'_crdt DEFAULT getdate() FOR '+ c.name
from sys.tables t
inner join sys.columns c on t.object_id=c.object_id
where c.name like '%your column name%'
Here's another method:
DECLARE #SQL nvarchar(max);
SELECT #SQL = Coalesce(#SQL + '
', '')
+ 'ALTER TABLE ' + QuoteName(T.TABLE_SCHEMA) + '.' + QuoteName(T.TABLE_NAME)
+ ' ADD CONSTRAINT ' + QuoteName('DF_'
+ CASE WHEN T.TABLE_SCHEMA <> 'dbo' THEN T.Table_Schema + '_' ELSE '' END
+ C.COLUMN_NAME) + ' DEFAULT (GetDate()) FOR ' + QuoteName(C.COLUMN_NAME)
+ ';'
FROM
INFORMATION_SCHEMA.TABLES T
INNER JOIN INFORMATION_SCHEMA.COLUMNS C
ON T.TABLE_SCHEMA = C.TABLE_SCHEMA
AND T.TABLE_NAME = C.TABLE_NAME
WHERE
C.COLUMN_NAME = 'CreatedDt'
;
EXEC (#SQL);
This yields, and runs, a series of statements similar to the following:
ALTER TABLE [schema].[TableName] -- (line break added)
ADD CONSTRAINT [DF_schema_TableName] DEFAULT (GetDate()) FOR [ColumnName];
Some notes:
This uses the INFORMATION_SCHEMA views. It is best practice to use these where possible instead of the system tables because they are guaranteed to not change between versions of SQL Server (and moreover are supported on many DBMSes, so all things being equal it's best to use standards-compliant/portable code).
In a database with a case-sensitive default collation, one MUST use upper case for the INFORMATION_SCHEMA view names and column names.
When creating script it's important to pay attention to schema names and proper escaping (using QuoteName). Not doing so will break in someone's system some day.
I think it is best practice to put the DEFAULT expression inside parentheses. While no error is received without it in this case, with it, if the function GetDate() is parameterized and/or ever changed to a more complex expression, nothing will break.
If you decide that column defaults are not going to work for you, then the triggers you imagined are still possible. But it will take some serious work to manage whether the trigger already exists and alter or create it appropriately, JOIN to the inserted meta-table inside the trigger, and do it based on the full list of primary key columns for the table (if they exist, and if they don't, then you're out of luck). It is quite possible, but extremely difficult--you could end up with nested, nested, nested dynamic SQL. I have such automated object-creating script that contains 13 quote marks in a row...

SQL Server 2008 mass alter statement for data type

I am trying to change data type from text to varchar in all of my tables at once.
This query
select *
from information_schema.columns
where data_type = 'text'
shows me all of my text data types, but how do I use this to then alter type to varchar.
I would change all of your text, ntext and image datatypes to the newer varchar(max), nvarchar(max) and varbinary(max) datatypes:
select 'alter table ' + quotename(c.TABLE_SCHEMA) + '.' + quotename(c.TABLE_NAME)
+ ' alter column ' + quotename(c.COLUMN_NAME) + ' '
+ case c.DATA_TYPE when 'image' then 'varbinary(max)' when 'ntext' then 'nvarchar(max)' when 'text' then 'varchar(max)' end + ' '
+ case c.IS_NULLABLE when 'YES' then 'not' else '' end + ' null;' as SqlCommand
, *
from INFORMATION_SCHEMA.COLUMNS c
join INFORMATION_SCHEMA.TABLES t on c.TABLE_CATALOG = t.TABLE_CATALOG
and c.TABLE_SCHEMA = t.TABLE_SCHEMA
and c.TABLE_NAME = t.TABLE_NAME
where c.DATA_TYPE in ('image', 'ntext', 'text')
and t.TABLE_TYPE = 'BASE TABLE'
Simply copy and run the SqlCommand column as a batch.
This will handle nullability and filter-out views.
I don't believe you can put any type unique constraint on a text/ntext/image column, so you probably don't have to check for PK/FK/UK. You would have to account for other types of constraints and defaults, however. If you have a lot of those, it might be easier to make these changes in SSMS diagram mode.
Copy these commands from query result and execute them:
select
cmd = 'alter table [' + c.table_schema + '].[' + c.table_name + '] alter column [' + c.column_name + '] varchar(<yoursize>)'
,*
from information_schema.columns c
where c.data_type='text'
But:
you need to join tables information to select only tables (query above would return views, too)
it won't let you alter some columns, e.g. with PK/FK constrints
this select may list also tables that you don't want to / cannot modify. E.g. sysdiagrams
It's generally not a good idea to do it like tht if you're not limiting it to few tables that you exactly know the structure of.
At first it may seem as simple as this:
Use a cursor loop over the select from information_schema.
Compose dynamic SQL for each column of interest that will change its datatype using an ALTER TABLE statement.
Execute the dynamic SQL.
However, you need to drop any indices on these columns first, foreign key constraints, etc.
Then when you are done, you can recreate the constraints and indices.
See this SO question:
Single SQL Query to update datatypes of all columns in a table at one shot