How to find who created index in SQL Server? [duplicate] - sql

Is it possibile to check who created indexes on SQL Server? I found only script which list time:
select STATS_DATE(so.object_id, index_id) StatsDate
, si.name IndexName
, schema_name(so.schema_id) + N'.' + so.Name TableName
, so.object_id, si.index_id
from sys.indexes si
inner join sys.tables so on so.object_id = si.object_id
order by StatsDate desc

In short, no. But if that's important for you to know for indexes created going forward, you can set up an event notification session or ddl trigger to track that information.

Related

Generating a DELETE script on all tables

We have a medium sized database, structure wise, and we need to go for a soft delete, to a hard delete. Part of the process is to actually delete rows where they have been soft deleted, before removing the Deleted column. I have generated a list of deletes, but I may hit a foreign key exception.
so, I ordered by 'object_id', in the hope that tables get added in an order and the object_id increased. No tables have been added since deployment.
So, would this be suitable?
SELECT 'DELETE FROM [' + ss.name + '].[' + st.name + '] WHERE DELETED IS NOT NULL'
FROM sys.tables st
INNER JOIN sys.schemas ss
ON ss.schema_id = st.schema_id
WHERE type='U'
AND st.name NOT IN ('JobRunLog', 'Log')
AND st.Object_ID IN(
SELECT DISTINCT(st.object_id)
FROM sys.tables st
INNER JOIN sys.columns cc
ON st.object_id = cc.object_id
AND cc.name = 'DELETED'
)
ORDER BY st.object_id DESC
I'm going backwards on object_id as I want to delete the last tables added, first. They could only have been created if the FK existed.

How to create a trigger for all tables in a SQL Server database

I have a column LastUpdate in all tables of my database and I want to say "on insert of update LastUpdate = getdate()"
I can do this with a trigger but I find it' hard to write hundreds triggers for each table of the database.
- How do I dynamically create a trigger that affect all tables?
- How do I dynamically create triggers for each table ?
It is not possible to have a trigger that fires when any table is updated.
You could generate the SQL Required dynamically, the following:
SELECT N'
CREATE TRIGGER trg_' + t.Name + '_Update ON ' + ObjectName + '
AFTER UPDATE
AS
BEGIN
UPDATE t
SET LastUpdate = GETDATE()
FROM ' + o.ObjectName + ' AS t
INNER JOIN inserted AS i
ON ' +
STUFF((SELECT ' AND t.' + QUOTENAME(c.Name) + ' = i.' + QUOTENAME(c.Name)
FROM sys.index_columns AS ic
INNER JOIN sys.columns AS c
ON c.object_id = ic.object_id
AND c.column_id = ic.column_id
WHERE ic.object_id = t.object_id
AND ic.index_id = ix.index_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 4, '') + ';
END;
GO'
FROM sys.tables AS t
INNER JOIN sys.indexes AS ix
ON ix.object_id = t.object_id
AND ix.is_primary_key = 1
CROSS APPLY (SELECT QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + QUOTENAME(t.name)) o (ObjectName)
WHERE EXISTS
( SELECT 1
FROM sys.columns AS c
WHERE c.Name = 'LastUpdate'
AND c.object_id = t.object_id
);
Generates SQL for each table with a LastUpdate column along the lines of:
CREATE TRIGGER trg_TableName_Update ON [dbo].[TableName]
AFTER UPDATE
AS
BEGIN
UPDATE t
SET LastUpdate = GETDATE()
FROM [dbo].[TableName] AS t
INNER JOIN inserted AS i
ON t.[PrimaryKey] = i.[PrimaryKey];
END;
GO
The relies on each table having a primary key to get the join from the inserted table back to the table being updated.
You can either copy and paste the results and execute them (I would recommend this way so you can at least check the SQL Generated, or build it into a cursor and execute it using sp_executesql. I would recommend the former, i.e. use this to save a bit of time, but still check each trigger before actually creating it.
I personally think last modified columns are a flawed concept, it always feels to me like storing annoyingly little information, if you really care about data changes then track them properly with an audit table (or temporal tables, or using Change Tracking). Firstly, knowing when something was changed, but not what it was changed from, or who changed it is probably more annoying than not knowing at all, secondly it overwrites all previous changes, what makes the latest change more important than all those that have gone before.

SQL how to know the datatype for a column

I'm using MS Access and MS Sql 2008, I need get the DataType for a specific column in a single table.
Could you please post a sample of code?
Try this:
SELECT
COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'schema'
AND TABLE_NAME = 'tablename';
You can also use catalog views:
SELECT sch.name [Schema],
tbl.name [Table],
col.name [Column],
typ.name [Type]
FROM sys.columns col
JOIN sys.tables tbl ON
tbl.object_id = col.object_id
AND tbl.name = 'tableName'
JOIN sys.schemas sch ON
sch.schema_id = tbl.schema_id
AND sch.name = 'schemaName'
JOIN sys.types typ ON
typ.system_type_id = col.system_type_id
I'm assuming that you want to programmatically get schema metadata for your MS Access DB, as there are other answers for SQL Server. Unfortunately, MS Access doesn't offer an information_schema catalog of views (or any real analog) to query directly, so you might have to try one of the following:
Create a linked server in SQL Server to your Access DB, and query through that.
Use something like GetOleDbSchemaTable in your app.

Drop tables by date it were created

I have a large database that were used to archive tables before implementing structural change on it.
We had this database for years, I want to create a dynamic script to check today's date and drop any table in this database that were created 3 years or older.
Thanks
For MS SQL Below script may serve your purpose
select
'drop table [' + s.name +'].[' + t.name +']' , t.create_date
from
sys.tables t
inner join
sys.schemas s
on
s.schema_id = t.schema_id
where
create_date< DATEADD(year,-3, GETDATE())
and type='U'

SQL Server: Get table primary key using sql query [duplicate]

This question already has answers here:
How do you list the primary key of a SQL Server table?
(28 answers)
Closed 3 years ago.
I want to get a particular table's primary key using SQL query for SQL Server database.
In MySQL I am using following query to get table primary key:
SHOW KEYS FROM tablename WHERE Key_name = 'PRIMARY'
What is equivalent of above query for SQL Server ?.
If There is a query that will work for both MySQL and SQL Server then It will be an ideal case.
I also found another one for SQL Server:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
AND TABLE_NAME = 'TableName' AND TABLE_SCHEMA = 'Schema'
Found another one:
SELECT
KU.table_name as TABLENAME
,column_name as PRIMARYKEYCOLUMN
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU
ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
AND KU.table_name='YourTableName'
ORDER BY
KU.TABLE_NAME
,KU.ORDINAL_POSITION
;
I have tested this on SQL Server 2003/2005
Using SQL SERVER 2005, you can try
SELECT i.name AS IndexName,
OBJECT_NAME(ic.OBJECT_ID) AS TableName,
COL_NAME(ic.OBJECT_ID,ic.column_id) AS ColumnName
FROM sys.indexes AS i INNER JOIN
sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID
AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
Found at SQL SERVER – 2005 – Find Tables With Primary Key Constraint in Database
From memory, it's either this
SELECT * FROM sys.objects
WHERE type = 'PK'
AND object_id = OBJECT_ID ('tableName')
or this..
SELECT * FROM sys.objects
WHERE type = 'PK'
AND parent_object_id = OBJECT_ID ('tableName')
I think one of them should probably work depending on how the data is stored
but I am afraid I have no access to SQL to actually verify the same.
SELECT COLUMN_NAME FROM {DATABASENAME}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME LIKE '{TABLENAME}' AND CONSTRAINT_NAME LIKE 'PK%'
WHERE
{DATABASENAME} = your database from your server AND
{TABLENAME} = your table name from which you want to see the primary key.
NOTE : enter your database name and table name without brackets.
select *
from sysobjects
where xtype='pk' and
parent_obj in (select id from sysobjects where name='tablename')
this will work in sql 2005
The code I'll give you works and retrieves not only keys, but a lot of data from a table in SQL Server. Is tested in SQL Server 2k5/2k8, dunno about 2k. Enjoy!
SELECT DISTINCT
sys.tables.object_id AS TableId,
sys.columns.column_id AS ColumnId,
sys.columns.name AS ColumnName,
sys.types.name AS TypeName,
sys.columns.precision AS NumericPrecision,
sys.columns.scale AS NumericScale,
sys.columns.is_nullable AS IsNullable,
( SELECT
COUNT(column_name)
FROM
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE
TABLE_NAME = sys.tables.name AND
CONSTRAINT_NAME =
( SELECT
constraint_name
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
TABLE_NAME = sys.tables.name AND
constraint_type = 'PRIMARY KEY' AND
COLUMN_NAME = sys.columns.name
)
) AS IsPrimaryKey,
sys.columns.max_length / 2 AS CharMaxLength /*BUG*/
FROM
sys.columns, sys.types, sys.tables
WHERE
sys.tables.object_id = sys.columns.object_id AND
sys.types.system_type_id = sys.columns.system_type_id AND
sys.types.user_type_id = sys.columns.user_type_id AND
sys.tables.name = 'TABLE'
ORDER BY
IsPrimaryKey
You can use only the primary key part, but I think that the rest might become handy.
Best regards,
David
This should list all the constraints and at the end you can put your filters
/* CAST IS DONE , SO THAT OUTPUT INTEXT FILE REMAINS WITH SCREEN LIMIT*/
WITH ALL_KEYS_IN_TABLE (CONSTRAINT_NAME,CONSTRAINT_TYPE,PARENT_TABLE_NAME,PARENT_COL_NAME,PARENT_COL_NAME_DATA_TYPE,REFERENCE_TABLE_NAME,REFERENCE_COL_NAME)
AS
(
SELECT CONSTRAINT_NAME= CAST (PKnUKEY.name AS VARCHAR(30)) ,
CONSTRAINT_TYPE=CAST (PKnUKEY.type_desc AS VARCHAR(30)) ,
PARENT_TABLE_NAME=CAST (PKnUTable.name AS VARCHAR(30)) ,
PARENT_COL_NAME=CAST ( PKnUKEYCol.name AS VARCHAR(30)) ,
PARENT_COL_NAME_DATA_TYPE= oParentColDtl.DATA_TYPE,
REFERENCE_TABLE_NAME='' ,
REFERENCE_COL_NAME=''
FROM sys.key_constraints as PKnUKEY
INNER JOIN sys.tables as PKnUTable
ON PKnUTable.object_id = PKnUKEY.parent_object_id
INNER JOIN sys.index_columns as PKnUColIdx
ON PKnUColIdx.object_id = PKnUTable.object_id
AND PKnUColIdx.index_id = PKnUKEY.unique_index_id
INNER JOIN sys.columns as PKnUKEYCol
ON PKnUKEYCol.object_id = PKnUTable.object_id
AND PKnUKEYCol.column_id = PKnUColIdx.column_id
INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
ON oParentColDtl.TABLE_NAME=PKnUTable.name
AND oParentColDtl.COLUMN_NAME=PKnUKEYCol.name
UNION ALL
SELECT CONSTRAINT_NAME= CAST (oConstraint.name AS VARCHAR(30)) ,
CONSTRAINT_TYPE='FK',
PARENT_TABLE_NAME=CAST (oParent.name AS VARCHAR(30)) ,
PARENT_COL_NAME=CAST ( oParentCol.name AS VARCHAR(30)) ,
PARENT_COL_NAME_DATA_TYPE= oParentColDtl.DATA_TYPE,
REFERENCE_TABLE_NAME=CAST ( oReference.name AS VARCHAR(30)) ,
REFERENCE_COL_NAME=CAST (oReferenceCol.name AS VARCHAR(30))
FROM sys.foreign_key_columns FKC
INNER JOIN sys.sysobjects oConstraint
ON FKC.constraint_object_id=oConstraint.id
INNER JOIN sys.sysobjects oParent
ON FKC.parent_object_id=oParent.id
INNER JOIN sys.all_columns oParentCol
ON FKC.parent_object_id=oParentCol.object_id /* ID of the object to which this column belongs.*/
AND FKC.parent_column_id=oParentCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/
INNER JOIN sys.sysobjects oReference
ON FKC.referenced_object_id=oReference.id
INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
ON oParentColDtl.TABLE_NAME=oParent.name
AND oParentColDtl.COLUMN_NAME=oParentCol.name
INNER JOIN sys.all_columns oReferenceCol
ON FKC.referenced_object_id=oReferenceCol.object_id /* ID of the object to which this column belongs.*/
AND FKC.referenced_column_id=oReferenceCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/
)
select * from ALL_KEYS_IN_TABLE
where
PARENT_TABLE_NAME in ('YOUR_TABLE_NAME')
or REFERENCE_TABLE_NAME in ('YOUR_TABLE_NAME')
ORDER BY PARENT_TABLE_NAME,CONSTRAINT_NAME;
For reference please read thru - http://blogs.msdn.com/b/sqltips/archive/2005/09/16/469136.aspx
Keep in mind that if you want to get exact primary field you need to put TABLE_NAME and TABLE_SCHEMA into the condition.
this solution should work:
select COLUMN_NAME from information_schema.KEY_COLUMN_USAGE
where CONSTRAINT_NAME='PRIMARY' AND TABLE_NAME='TABLENAME'
AND TABLE_SCHEMA='DATABASENAME'
It is also (Transact-SQL) ... according to BOL.
-- exec sp_serveroption 'SERVER NAME', 'data access', 'true' --execute once
EXEC sp_primarykeys #table_server = N'server_name',
#table_name = N'table_name',
#table_catalog = N'db_name',
#table_schema = N'schema_name'; --frequently 'dbo'