I have around 150 tables in my database and now I need to add a column constraint(InsertedOn) on to each and every table with a default value of GetDate()
I have tried below code to accomplish the task
exec sp_msforeachtable 'ALTER TABLE ? ADD CONSTRAINT DF_InsertedOn DEFAULT GetDate() FOR [InsertedOn]';
But my problem is constraint name,The above code fails when its trying to create the constraint for the second table since the name of the constraint in use
Is there any way to accomplish the task using the same sp_msforeachtable ?
Thank you.
Try this one -
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = STUFF((
SELECT CHAR(13) + 'ALTER TABLE [' + s.name + '].[' + o.name + ']
ADD [InsertedOn] DATETIME NOT NULL CONSTRAINT [DF_' + o.name + '_InsertedOn] DEFAULT GETDATE()'
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
WHERE NOT EXISTS(
SELECT 1
FROM sys.columns c WITH (NOWAIT)
WHERE c.[object_id] = o.[object_id]
AND c.name = 'InsertedOn'
)
AND o.[type] = 'U'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
PRINT #SQL
EXEC sys.sp_executesql #SQL
Output -
ALTER TABLE [tt].[t1]
ADD [InsertedOn] DATETIME NOT NULL CONSTRAINT [DF_t1_InsertedOn] DEFAULT GETDATE()
ALTER TABLE [tt].[t2]
ADD [InsertedOn] DATETIME NOT NULL CONSTRAINT [DF_t2_InsertedOn] DEFAULT GETDATE()
To generate scrips you can use this code. It uses system views sys.tables, sys.schemas and sys.columns
DECLARE #ColumnName VARCHAR(100) = 'InsertedOn'
SELECT
'ALTER TABLE ' + s.name + '.' + t.name +
' ADD CONSTRAINT DF_' + t.name + '_' + #ColumnName +
' DEFAULT GetDate() FOR ' + #ColumnName
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE EXISTS (
SELECT *
FROM sys.columns c
WHERE c.object_id = t.object_id
AND name = #ColumnName
)
Related
I have a schema where I have multiple tables some with time and some without it. So I created a query where I have listed 3 tables say which has time like this :
WITH CTE AS
(
SELECT
CONCAT(schema_name(t.schema_id), '.', t.name) AS table_name,
c.name AS 'time'
FROM
sys.tables t
INNER JOIN
sys.columns c ON c.object_id = t.object_id
WHERE
schema_name(t.schema_id) = 'Prod'
AND c.name = 'mytime'
)
SELECT * FROM CTE
Now my output looks like ( I am showing 3 rows for the example):
Table O
table_name time
--------------------------
Prod.tableA mytime
Prod.tableB mytime
Prod.tableC mytime
So usually what I want is to get the max(mytime) from each Table/Schema combination . So for a single table I can do
SELECT MAX(mytime)
FROM Prod.tableA
However in this case I want to generate this from table O for each table and my output should look like:
Table F
table_name mymax(time)
--------------------------------------------
Prod.tableA max(mytime) from Prod.tableA
Prod.tableB max(mytime) from Prod.tableA
Prod.tableC max(mytime) from Prod.tableA
How to achieve this using another select/variable declaration etc? Any help or ideas will be extremely appreciated. Thanks in anticipation.
Can this help? You still have a bit of work, check if the output is what you like and then uncomment the exec.
DECLARE #SchemaName NVARCHAR(100) = 'foo',
#ColumnName NVARCHAR(100) = 'bar',
#sql NVARCHAR(max)
SELECT #SchemaName + '.'+ t.name AS [Schema.Table],'( SELECT MAX(' + #ColumnName + ') FROM ['+ #SchemaName +'].['+t.name+']) ' AS MaxValue
FROM sys.tables t
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = #SchemaName
-------
SELECT #sql =
STUFF((
SELECT 'UNION ALL ' + 'SELECT ' + '''' + '[' + ISNULL(#SchemaName,'') + '].['+ t.name + ']' + '''' + ' AS [Schema.Table] ,( SELECT MAX(' + #ColumnName + ') FROM ['+ #SchemaName +'].['+t.name+']) AS Max' + #ColumnName + ' '
FROM sys.tables t
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = #SchemaName
for xml path('')
),1,10,'')
PRINT #sql
--EXEC(#sql)
I have this stored procedure and I want to revise it to be to rebuild more than one index.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [Landing].[usp_IndexDisableRebuild]
(#Schema_Name VARCHAR(256),
#Table_Name VARCHAR(256),
#Task_Name VARCHAR(256))
AS
-- Set to get the dynamic Script for
DECLARE #sql VARCHAR(MAX)
SET #sql = (SELECT 'ALTER INDEX ' + QUOTENAME(I.name) + ' ON ' + QUOTENAME(SCHEMA_NAME(T.schema_id))+'.'+ QUOTENAME(T.name) + #Task_Name FROM sys.indexes I INNER JOIN sys.tables T ON I.object_id = T.object_id INNER Join sys.schemas s ON s.schema_id = t.schema_id WHERE I.type_desc = 'NONCLUSTERED' AND I.name IS NOT NULL --AND I.is_disabled = 0 AND t.name = #Table_Name AND s.name = #Schema_Name )
-- Execute the dynamic SQL
EXEC (#sql)
I agree with the comments that you should consider using Ola Hallengren's SQL Server Maintenance Solution.
That being said, you could change your proc like to example below. In addition to correcting the subquery error, this uses the proper data types. Not sure what you want to do with #Task_Name so I just appended the value as a comment.
ALTER PROCEDURE [Landing].[usp_IndexDisableRebuild]
#Schema_Name sysname,
#Table_Name sysname,
#Task_Name VARCHAR(256)
AS
DECLARE #SQL nvarchar(MAX);
SET #SQL = (
SELECT 'ALTER INDEX ' + QUOTENAME(I.name)
+ ' ON ' + QUOTENAME(SCHEMA_NAME(T.schema_id))+'.'+ QUOTENAME(T.name) + ' REBUILD;
--' + #Task_Name + '
'
FROM sys.indexes I
INNER JOIN sys.tables T ON I.object_id = T.object_id
INNER Join sys.schemas s ON s.schema_id = t.schema_id
WHERE I.type_desc = 'NONCLUSTERED'
AND I.name IS NOT NULL
AND I.is_disabled = 0
AND t.name = #Table_Name
AND s.name = #Schema_Name
FOR XML PATH(''), TYPE).value('.','nvarchar(MAX)');
--PRINT #SQL;
EXECUTE sp_executesql #SQL;
GO
I am trying to drop all tables in a database without having to do it in the proper order. From what I have read running the NOCHECK command will prevent foreign keys from being checked. However, even after running that I still get an error trying to drop the first table.
Could not drop object 'dbo.TABLENAME' because it is referenced by
a FOREIGN KEY constraint
I have seen this question answered successfully before so I don't understand what is different with what I am doing. This is running on SQL Server 2008 R2.
BEGIN TRANSACTION
--get current list of tables
SELECT QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) as 'Dropped Table'
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
--disable constraint checking in all tables
DECLARE #sql NVARCHAR(max)
SET #sql = ''
SELECT #sql += ' ALTER TABLE ' + QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + ' NOCHECK CONSTRAINT ALL; '
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
select #sql
Exec sp_executesql #sql
--disable all constraints (this also didn't work)
--EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
--drop all tables
SET #sql = ''
SELECT #sql += ' DROP TABLE ' + QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + '; '
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
select #sql
Exec sp_executesql #sql
--check current list, should be empty
SELECT QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) as 'Tables'
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
ROLLBACK TRANSACTION
Update 1
I removed the constraint disabling code in place of constraint dropping code but it gives and error.
--drop all constraints
DECLARE #sql NVARCHAR(max)
SET #sql = ''
SELECT #sql += ' ALTER TABLE ' +QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + ' DROP CONSTRAINT ' + ctu.CONSTRAINT_NAME + ';'
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
INNER JOIN EOS_DEV.INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE as ctu
ON ctu.TABLE_SCHEMA = s.name AND ctu.TABLE_NAME = t.name
WHERE t.type = 'U'
Exec sp_executesql #sql
The constraint '[CONSTRAINT_NAME]' is being referenced by table
'[TABLE_NAME]', foreign key constraint '[FK_NAME]'
How can I modify this query so I only target FK constraints?
Thanks everyone for your help. I updated my query and can now confirm that it has the ability to drop all tables indiscriminately. I also added a section to drop all stored procs for a little added flavor.
BEGIN TRANSACTION
--get current list of tables
SELECT QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) as 'Dropped Table'
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
--drop all constraints
DECLARE #sql NVARCHAR(max)
SET #sql = ''
SELECT #sql += ' ALTER TABLE ' +QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + ' DROP CONSTRAINT ' + tc.CONSTRAINT_NAME + ';'
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
INNER JOIN EOS_DEV.INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
ON tc.TABLE_SCHEMA = s.name AND tc.TABLE_NAME = t.name
WHERE t.type = 'U'
AND tc.CONSTRAINT_TYPE = 'FOREIGN KEY'
Exec sp_executesql #sql
--drop all tables
SET #sql = ''
SELECT #sql += ' DROP TABLE ' + QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + '; '
FROM sys.tables t
JOIN sys.schemas s
ON t.[schema_id] = s.[schema_id]
WHERE t.type = 'U'
Exec sp_executesql #sql
--drop all stored procs
SET #sql = ''
SELECT #sql += 'DROP PROCEDURE [' + SCHEMA_NAME(p.schema_id) + '].[' + p.NAME + ']'
FROM sys.procedures as p
where p.is_ms_shipped = 0
AND p.type = 'P'
Exec sp_executesql #sql
ROLLBACK TRANSACTION
Setting a FK to NOCHECK will allow you to INSERT,UPDATE, or DELETE rows that would violate the constraint. It will not allow you to DROP or TRUNCATE the target table.
EG:
use tempdb
create table a(id int primary key)
create table b(id int primary key, aid int references a)
alter table b nocheck constraint all
insert into b(id,aid) values (1,1) --succeeds because of nocheck
drop table a --fails
--Msg 3726, Level 16, State 1, Line 11
--Could not drop object 'a' because it is referenced by a FOREIGN KEY constraint.
Do you have to make this so difficult? Why not just restore an empty database (or a database that contains just your schema and whatever "default" rows are needed)?
I am trying to select Max(ID) for all tables in my database. I tried the below query but there is no AUTO-INCREMENT column available. Is there something else that I can try?
SELECT TABLE_NAME, AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb'
Are you trying to get the max value for each IDENTITY column in your DB? that is possible by modifying the script in a previous answer to examine the is_identity column on the sys.columns table.
CREATE TABLE #x(t NVARCHAR(520), c BIGINT);
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'INSERT #x SELECT '''
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ''',
MAX(' + c.name + ') FROM '
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ';'
FROM sys.columns C
INNER JOIN sys.tables T ON C.object_id = T.object_id
INNER JOIN sys.schemas s ON S.schema_id = T.schema_id
WHERE is_identity = 1;
EXEC sp_executesql #sql;
SELECT t, c FROM #x;
DROP TABLE #x;
CREATE TABLE #x(t NVARCHAR(520), c BIGINT);
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'INSERT #x SELECT '''
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ''',
MAX(ID) FROM '
+ QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ';'
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
INNER JOIN sys.columns AS c
ON t.[object_id] = c.[object_id]
WHERE c.name = N'ID';
EXEC sp_executesql #sql;
SELECT t, c FROM #x;
DROP TABLE #x;
I have a database in sql server 2008 R2 that have many table (over 200) and have many relation betweens tables.
Delete rule in most of relations is No Action
I need to Update all relation delete rule to Cascade at once
Because of too many relation in my database I dont want do this one by one
Is there any way ?
Typically, when you ALTER a Foreign key constraint, using the SSMS GUI, SQL Server on the background actually drops and recreates the same.
Here is a script, that will generate the SQL for dropping all FKeys and recreating them with ON UPDATE CASCADE ON DELETE CASCADE options
Assumption is, all your FKeys are name "FK....."
SET NOCOUNT ON;
DECLARE #Objects TABLE
(
ID int identity(1,1),
TableName sysname,
SchemaName sysname
)
INSERT INTO #Objects (TableName, SchemaName)
SELECT
TABLE_NAME,
CONSTRAINT_SCHEMA
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE CONSTRAINT_NAME LIKE 'FK%'
DECLARE #min int, #max int,#table sysname,#schema sysname
SELECT #min = 1, #max = MAX(ID) FROM #Objects
WHILE #min <=#max
BEGIN
SELECT
#table = TableName,#schema = SchemaName FROM #Objects WHERE ID = #min
print '/*Drop Foreign Key Statements for [' + #schema + '].[' + #table + ']*/'
SELECT
'ALTER TABLE [' + SCHEMA_NAME(o.schema_id) + '].[' + o.name + ']
DROP CONSTRAINT [' + fk.name + ']'
FROM sys.foreign_keys fk
INNER JOIN sys.objects o
ON fk.parent_object_id = o.object_id
WHERE o.name = #table AND
SCHEMA_NAME(o.schema_id) = #schema
print '/*Create Foreign Key Statements for ['
+ #schema + '].[' + #table + ']*/'
SELECT
'ALTER TABLE [' + SCHEMA_NAME(o.schema_id) + '].[' + o.name + ']
ADD CONSTRAINT [' + fk.name + '] FOREIGN KEY ([' + c.name + '])
REFERENCES [' + SCHEMA_NAME(refob.schema_id) + '].[' + refob.name + ']
([' + refcol.name + '])ON UPDATE CASCADE ON DELETE CASCADE'
FROM sys.foreign_key_columns fkc
INNER JOIN sys.foreign_keys fk
ON fkc.constraint_object_id = fk.object_id
INNER JOIN sys.objects o
ON fk.parent_object_id = o.object_id
INNER JOIN sys.columns c
ON fkc.parent_column_id = c.column_id AND
o.object_id = c.object_id
INNER JOIN sys.objects refob
ON fkc.referenced_object_id = refob.object_id
INNER JOIN sys.columns refcol
ON fkc.referenced_column_id = refcol.column_id AND
fkc.referenced_object_id = refcol.object_id
WHERE o.name = #table AND
SCHEMA_NAME(o.schema_id) = #schema
SET #min = #min+1
END
Hope this helps.
Raj
PS: Setting query output to text helps. Also please read the comment posted on your question. Arbitrarily setting CASCADE may not be the right thing to do