Find Multi-Column Primary key - sql-server

I have about 30 tables from an old ERP which have multi-column primary keys. Unfortunately I don't know what those keys are. I've used the SSIS profiling task to determine primary key candidates for up to 5 columns, but it runs so slow as to be impractical. Is there any tool that would do this faster? My alternative is about 2 weeks of investigation using Excel and lots of select distinct queries.

The following should get you what you're looking for.
SELECT
*
FROM (
SELECT
i.object_id,
index_name = i.name,
key_column_name = c.name,
ic.key_ordinal,
key_col_cnt = MAX(ic.key_ordinal) OVER (PARTITION BY ic.object_id)
FROM
sys.indexes i
JOIN sys.index_columns ic
ON i.object_id = ic.object_id
AND i.index_id = ic.index_id
JOIN sys.columns c
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
WHERE
i.is_primary_key = 1
) ix
WHERE
ix.key_col_cnt > 1;

As it turns out I was able to get primary keys for many tables by reverse-engineering with ER/Studio using an ODBC driver.
I have no idea how they manage to get the primary keys (the reports produced by the database don't show them), but for most table it seems like they're there.

Related

Check if any database table has any rows

I am trying to understand how to check if any table in my db has data using entity framework. I can check for one table but how can I check for all tables at once? DO we have any option with ef6?
using (var db = new CreateDbContext())
{
if(!db.FirstTable.Any())
{
// The table is empty
}
}
Any pointers on how to loop through entities would be helpful.
Here is one way you could do this with t-sql. This should be lightning fast on most systems. This returned in less than a second on our ERP database. It stated 421 billion rows in more than 15,000 partition stats.
select sum(p.row_count)
from sys.dm_db_partition_stats p
join sys.objects o on o.object_id = p.object_id
where o.type not in ('S', 'IT') --excludes system and internal tables.
Similar to #SeanLange, but shows schema name and table name for tables without any rows.
SELECT Distinct OBJECT_SCHEMA_NAME(p.object_id) AS [Schema],
OBJECT_NAME(p.object_id) AS [Table]
FROM sys.partitions p
INNER JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
WHERE OBJECT_SCHEMA_NAME(p.object_id) != 'sys'
And p.Rows = 0
ORDER BY [Schema], [Table]

How to the indexes created in a DB the last 2 months in SQL Server

I have created indexes on my DB the last 2 months. Everything works fine. However, now I have to move those indexes to the UAT ENV. I kept track of the indexes I created. However I want to be sure I didn't miss any. How do I know the indexes created in the last 2 months using a query?
SQL Server does not maintain index creation information for indexes in a DMV. This is not information you can query.
You can get this information for PK, unique indexes or unique constraints.
See Kendra Little's blog here for some good info on this topic.
From Kendra's post:
But if you’re not looking for the create date of a Primary Key, unique index, or unique constraint, you’re out of luck.
What you probably need is to check the indexes in the database through the catalog views. Maybe something like this can help you:
SELECT
t.name AS TableName,
ind.name AS IndexName,
col.name AS ColumnName,
STATS_DATE(t.object_id,ind.index_id)
FROM sys.indexes ind
INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN sys.tables t ON ind.object_id = t.object_id
WHERE STATS_DATE(t.object_id,ind.index_id) > DATEADD(mm,-2,GETDATE())
ORDER BY TableName, IndexName, ColumnName
Remember to run in the database you have to check your indexes and not in the master.
Thanks for all the responses. There is really no good way to find the indexes created in last two months. The best way is to load the indexes in a table and compare them with DEV Indexes.

given a foreign key, how do i find all tables that use that particular key?

i have a column (myColumn) that serves as the primary key of a table (tableA).
i've noticed that 2 or 3 tables reference this myColumn as foreign key.
how do i detect all tables that use and reference myColumn?
im guessing that more than 3 tables use myColumn because when i tried updating it like this
UPDATE tableA
SET myColumn = 1
WHERE myColumn = 1
6 rows were updated.
it was earlier suggested to me to use
sp_helpconstraint('your_table_name')
but i then found out that this does not give the complete information that i need.
any other suggestions?
Try this - this is the more up-to-date, SQL Server 2005 and newer version of my original answer that Mitch linked to (that was for SQL Server 2000):
SELECT
ConstraintName = fk.name,
TableName = t.name,
ColumnName = c.name
FROM
sys.foreign_keys fk
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
sys.tables t ON fk.parent_object_id = t.object_id
INNER JOIN
sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id
INNER JOIN
sys.tables tref ON fk.referenced_object_id = tref.object_id
INNER JOIN
sys.columns cref ON fkc.referenced_object_id = cref.object_id AND fkc.referenced_column_id = cref.column_id
WHERE
tref.Name = 'Person'
AND cref.Name = 'OID'
It uses the system catalog views sys.foreign_keys and sys.foreign_key_columns to find out which tables/columns reference that table and column you're interested in.
You just basically type in the table name and the column name in the WHERE clause - and you get your list of other tables/columns referencing that table/column
If you install Redgate's free sql search tool you can easily search your database schema for strings such as tables and column names.
http://www.red-gate.com/products/sql-development/sql-search/
There are other ways to search the schema using system tables but I highly recommend this tool. It will become part of your everyday workflow if you are constantly reverse engineering large databases.

Retention period in SQL Server 2008 Change Tracking

I'm a little worried about the default retention period in SQL Server 2008 Change Tracking (which is 2 days).
Is it a good idea to set this period to eg. 100 years and turn auto cleanup off or will it bite me back in the future with excessive storage usage and/or performance degradation? Anyone has experience in that matter?
If you set auto cleanup off, it's best to periodically go through and remove the change tracking information yourself, by disabling and then re-enabling change tracking for each table. Otherwise, yes, the tracking data will continue to grow and grow.
You can't query the underlying tables directly, but you can poke at their metadata. The following query shows relative row counts:
select
s.name as schema_name
, t.name as table_name
, (select sum(rows) from sys.partitions x where o.parent_object_id = x.object_id) as rows_in_base_table
, o.name as tracking_table
, p.rows as rows_in_tracking_table
from sys.objects o
join sys.tables t on o.parent_object_id = t.object_id
join sys.schemas s on t.schema_id = s.schema_id
join sys.partitions p on o.object_id = p.object_id
where o.name like 'change[_]tracking%'
and o.schema_id = schema_id('sys')
order by schema_name, table_name
Run that in your database, and you should get a rough sense of current overhead.
The change tracking tables all follow a standard schema. For example:
select
c.name, c.column_id
, type_name(user_type_id) as type_name
, c.max_length, c.precision, c.scale
, c.is_nullable, c.is_identity
from sys.columns c
where object_id = (
select top 1 object_id from sys.objects o
where o.name like 'change[_]tracking%'
and o.schema_id = schema_id('sys')
)
The k_% columns vary by table and correspond to the primary keys of the tracked table. You are looking at a base minimum overhead of 18 bytes + (primary key length) per row. That adds up!
For example, I'm tracking some skinny base tables that are only 15 bytes wide, with a 7-byte composite key. That makes the tracking tables 18+7=25 bytes wide!

How to find all the columns of a particular index in SQL Server?

Suppose I have a UNIQUE CLUSTERED INDEX on a table which has 3 columns. What would be an efficient way to get the columns on providing this index name?
The following example returns all indexes and index columns for the table myTbl.
SELECT i.name AS index_name
,COL_NAME(ic.object_id,ic.column_id) AS column_name
,ic.index_column_id
,ic.key_ordinal
,ic.is_included_column
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.object_id = OBJECT_ID('myTbl');
Source here
Well, you can go to the Index folder in SSMS under that DB > Table and script out the Index to see everything about it. Or just right click on the index and click Properties, and the columns will be listed under General

Resources