I am using a third party application which has an absurd number of columns per table. When I select data, often I need all columns except the ID. Or all columns except ID and DateCreated.
Using the sys.columns it's possible to find out which columns are available in a table. How can I use this information to create statements? What would be the best way to do this?
This script will select all columns for any table except the primary key column of the table and the column names DateCreated.
SELECT
'SELECT '+
SUBSTRING(LIST,1,LEN(LIST)-1)
+' FROM [Person].[Address]'
FROM
(
SELECT
'['+COL.COLUMN_NAME+'],'
FROM INFORMATION_SCHEMA.COLUMNS COL
LEFT JOIN
(
SELECT
CON.CONSTRAINT_TYPE,
USG.TABLE_SCHEMA,
USG.TABLE_NAME,
USG.COLUMN_NAME,
CON.CONSTRAINT_NAME,
USG.TABLE_CATALOG
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE USG
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS CON
ON USG.CONSTRAINT_NAME = CON.CONSTRAINT_NAME
)Q
ON COL.TABLE_SCHEMA = Q.TABLE_SCHEMA
AND COL.TABLE_NAME = Q.TABLE_NAME
AND COL.TABLE_CATALOG = Q.TABLE_CATALOG
AND COL.COLUMN_NAME = Q.COLUMN_NAME
WHERE COL.TABLE_SCHEMA ='Person'
AND COL.TABLE_NAME = 'Address'
AND
(
Q.CONSTRAINT_TYPE <> 'PRIMARY KEY'
OR
COL.COLUMN_NAME <> 'DateCreated'
)
FOR XML PATH(''))L(LIST)
Replace the string Person with your schema and Address With you table name
try using dynamic Query:
DECLARE #Names VARCHAR(MAX)
SELECT #Names = COALESCE(#Names + ', ', '') + Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Table_name='Table1'
And Column_Name!='ID'
DECLARE #Query VARCHAR(MAX)
SELECT #Query = 'SELECT '+ #Names + ' INTO Table2 FROM Table1'
exec (#Query)
SELECT * from Table2
I have to compare table (SIB$) to get unmatched records on two different LINKED SERVERS (LATESTDUMP, OLDDUMP) that are identical. I have already tried to create a dynamic query. Can some one please help me with following:
1) Is there a way where I dont have to pass the column names to the code and the code dynamically gets the column names and use it as the column list to compare.
So all I have to do is pass to the stored proc the two table names
Code i have worked on:
DECLARE #sql nvarchar(max) = ' ((SELECT * FROM LATESTDUMP...SIB$) t1 FULL
OUTER JOIN (SELECT * FROM OLDDUMP...SIB$) t2
ON t1.id = t2.id
WHERE
t1.id IS NULL OR
t2.id IS NULL)'
SELECT #sql += ' or t1.' + quotename(column_name) + ' <> t2.' +
quotename(column_name) from information_schema.columns where table_name =
'SIB$'
Looks like you might want to look at the MERGE statement that's been available since SQL 2008.
https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql
Here's some code to get you started. It pulls out a primary key (assumes one column primary keys, which may or may not be a valid assumption for you), and grabs a comma-delimited string list of the remaining columns.
From here you can use split-string to build a sql string that joins the two same-named tables from the hard-coded linked servers on the primary key, comparing each of the columns for difference, and then execute the dynamic SQL. I've included some test scaffolding so you can work it through:
DECLARE #tableName sysname;
SET #tableName = 'some table'
-- Validate parameter
IF #tableName IS NULL OR NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #tableName AND TABLE_TYPE = 'BASE TABLE')
BEGIN
RAISERROR ('Invalid table name specified', 16, 1);
RETURN;
END;
-- Validate table has a primary key
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = #tableName)
BEGIN
RAISERROR ('Specified table does not have a primary key', 16, 1);
RETURN;
END;
-- Get info about the Primary Key columns
DECLARE #pkcolName sysname;
SELECT #pkcolName = c.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.COLUMNS c ON kcu.TABLE_NAME = c.TABLE_NAME AND kcu.COLUMN_NAME = c.COLUMN_NAME
WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' AND tc.TABLE_NAME = #tableName AND kcu.ORDINAL_POSITION = 1
-- Grab the names of all the remaining columns
DECLARE #nonKeyColumns nvarchar(MAX);
SELECT #nonKeyColumns = STUFF ( ( SELECT N'], [' + c.name
FROM sys.columns c
WHERE object_id = (select top 1 object_id FROM sys.objects where name = #tableName)
AND c.name <> #pkcolName
ORDER BY c.column_id
FOR XML PATH('')), 1, 2, '') + ']';
SELECT #pkcolName
SELECT #nonKeyColumns
Normally, I use this code to find a column in my table:
Use MyDatabase
Go
IF EXISTS(SELECT * FROM sys.columns
WHERE Name in ( N'String1')
AND Object_ID = Object_ID(N'dbo.Table1'))
BEGIN
Print 'Column String1 exists in Table1'
END
ELSE
BEGIN
Print 'Column String1 does not exist in Table1'
END;
We're updating the table and adding 56 new columns. How do I go about that without duplicating the code 56 times? It's just a quick error check to do after importing the new columns. Another thing I'd like to do is just print out the result only if the column isn't found.
Thanks!
Matt
You can declare a table containing all the 56 column names you want to check and then left join it against the management view:
DECLARE #cols TABLE
(
column_name varchar(500)
)
INSERT INTO #cols
VALUES ('col1'),('col2'),('col3')
IF EXISTS (SELECT *
FROM #cols c
LEFT JOIN INFORMATION_SCHEMA.COLUMNS col ON col.COLUMN_NAME = c.column_name
AND col.TABLE_NAME = 'Table1'
WHERE col.TABLE_NAME IS NULL)
BEGIN
PRINT 'Some columns are missing'
SELECT c.column_name
FROM #cols c
LEFT JOIN INFORMATION_SCHEMA.COLUMNS col ON col.COLUMN_NAME = c.column_name
AND col.TABLE_NAME = 'Table1'
WHERE col.TABLE_NAME IS NULL
END
INFORMATION_SCHEMA.COLUMNS is functionally the same as sys.columns. I prefer it for being cleaner and have more info than sys.columns.
I'm trying to identify which tables are affected by a data update though an application (developed by others). There are more than 200 tables in the DB and I'd like to avoid checking each of them for changes.
Is there any other way where I can list all table names along with their row count?
select table_name from information_schema.tables
List out all the tables in my DB buy how do I include number of rows as well?
SELECT sc.name +'.'+ ta.name TableName
,SUM(pa.rows) RowCnt
FROM sys.tables ta
INNER JOIN sys.partitions pa
ON pa.OBJECT_ID = ta.OBJECT_ID
INNER JOIN sys.schemas sc
ON ta.schema_id = sc.schema_id
WHERE ta.is_ms_shipped = 0 AND pa.index_id IN (1,0)
GROUP BY sc.name,ta.name
ORDER BY SUM(pa.rows) DESC
See this:
SQL SERVER – Find Row Count in Table – Find Largest Table in Database.
to get all tables in a database:
select * from INFORMATION_SCHEMA.TABLES
to get all columns in a database:
select * from INFORMATION_SCHEMA.columns
to get all views in a db:
select * from INFORMATION_SCHEMA.TABLES where table_type = 'view'
Posted for completeness.
If you are looking for row count of all tables in all databases (which was what I was looking for) then I found this combination of this and this to work. No idea whether it is optimal or not:
SET NOCOUNT ON
DECLARE #AllTables table (DbName sysname,SchemaName sysname, TableName sysname, RowsCount int )
DECLARE
#SQL nvarchar(4000)
SET #SQL='SELECT ''?'' AS DbName, s.name AS SchemaName, t.name AS TableName, p.rows AS RowsCount FROM [?].sys.tables t INNER JOIN sys.schemas s ON t.schema_id=s.schema_id INNER JOIN [?].sys.partitions p ON p.OBJECT_ID = t.OBJECT_ID'
INSERT INTO #AllTables (DbName, SchemaName, TableName, RowsCount)
EXEC sp_msforeachdb #SQL
SET NOCOUNT OFF
SELECT DbName, SchemaName, TableName, SUM(RowsCount), MIN(RowsCount), SUM(1)
FROM #AllTables
WHERE RowsCount > 0
GROUP BY DbName, SchemaName, TableName
ORDER BY DbName, SchemaName, TableName
Try this it's simple and fast
SELECT T.name AS [TABLE NAME], I.rows AS [ROWCOUNT]
FROM sys.tables AS T
INNER JOIN sys.sysindexes AS I ON T.object_id = I.id
AND I.indid < 2 ORDER BY I.rows DESC
I want to create a list of columns in SQL Server 2005 that have identity columns and their corresponding table in T-SQL.
Results would be something like:
TableName, ColumnName
Another potential way to do this for SQL Server, which has less reliance on the system tables (which are subject to change, version to version) is to use the
INFORMATION_SCHEMA views:
select COLUMN_NAME, TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
sys.columns.is_identity = 1
e.g.,
select o.name, c.name
from sys.objects o inner join sys.columns c on o.object_id = c.object_id
where c.is_identity = 1
Another way (for 2000 / 2005/2012/2014):
IF ((SELECT OBJECTPROPERTY( OBJECT_ID(N'table_name_here'), 'TableHasIdentity')) = 1)
PRINT 'Yes'
ELSE
PRINT 'No'
NOTE: table_name_here should be schema.table, unless the schema is dbo.
In SQL 2005:
select object_name(object_id), name
from sys.columns
where is_identity = 1
This query seems to do the trick:
SELECT
sys.objects.name AS table_name,
sys.columns.name AS column_name
FROM sys.columns JOIN sys.objects
ON sys.columns.object_id=sys.objects.object_id
WHERE
sys.columns.is_identity=1
AND
sys.objects.type in (N'U')
List of tables without Identity column based on Guillermo answer:
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (TABLE_SCHEMA = 'dbo') AND (OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 0)
ORDER BY TABLE_NAME
here's a working version for MSSQL 2000. I've modified the 2005 code found here: http://sqlfool.com/2011/01/identity-columns-are-you-nearing-the-limits/
/* Define how close we are to the value limit
before we start throwing up the red flag.
The higher the value, the closer to the limit. */
DECLARE #threshold DECIMAL(3,2);
SET #threshold = .85;
/* Create a temp table */
CREATE TABLE #identityStatus
(
database_name VARCHAR(128)
, table_name VARCHAR(128)
, column_name VARCHAR(128)
, data_type VARCHAR(128)
, last_value BIGINT
, max_value BIGINT
);
DECLARE #dbname sysname;
DECLARE #sql nvarchar(4000);
-- Use an cursor to iterate through the databases since in 2000 there's no sp_MSForEachDB command...
DECLARE c cursor FAST_FORWARD FOR
SELECT
name
FROM
master.dbo.sysdatabases
WHERE
name NOT IN('master', 'model', 'msdb', 'tempdb');
OPEN c;
FETCH NEXT FROM c INTO #dbname;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'Use [' + #dbname + '];
Insert Into #identityStatus
Select ''' + #dbname + ''' As [database_name]
, Object_Name(id.id) As [table_name]
, id.name As [column_name]
, t.name As [data_type]
, IDENT_CURRENT(Object_Name(id.id)) As [last_value]
, Case
When t.name = ''tinyint'' Then 255
When t.name = ''smallint'' Then 32767
When t.name = ''int'' Then 2147483647
When t.name = ''bigint'' Then 9223372036854775807
End As [max_value]
From
syscolumns As id
Join systypes As t On id.xtype = t.xtype
Where
id.colstat&1 = 1 -- this identifies the identity columns (as far as I know)
';
EXECUTE sp_executesql #sql;
FETCH NEXT FROM c INTO #dbname;
END
CLOSE c;
DEALLOCATE c;
/* Retrieve our results and format it all prettily */
SELECT database_name
, table_name
, column_name
, data_type
, last_value
, CASE
WHEN last_value < 0 THEN 100
ELSE (1 - CAST(last_value AS FLOAT(4)) / max_value) * 100
END AS [percentLeft]
, CASE
WHEN CAST(last_value AS FLOAT(4)) / max_value >= #threshold
THEN 'warning: approaching max limit'
ELSE 'okay'
END AS [id_status]
FROM #identityStatus
ORDER BY percentLeft;
/* Clean up after ourselves */
DROP TABLE #identityStatus;
The following query work for me:
select TABLE_NAME tabla,COLUMN_NAME columna
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
I think this works for SQL 2000:
SELECT
CASE WHEN C.autoval IS NOT NULL THEN
'Identity'
ELSE
'Not Identity'
AND
FROM
sysobjects O
INNER JOIN
syscolumns C
ON
O.id = C.id
WHERE
O.NAME = #TableName
AND
C.NAME = #ColumnName
This worked for me using Sql Server 2008:
USE <database_name>;
GO
SELECT SCHEMA_NAME(schema_id) AS schema_name
, t.name AS table_name
, c.name AS column_name
FROM sys.tables AS t
JOIN sys.identity_columns c ON t.object_id = c.object_id
ORDER BY schema_name, table_name;
GO
Use this :
DECLARE #Table_Name VARCHAR(100)
DECLARE #Column_Name VARCHAR(100)
SET #Table_Name = ''
SET #Column_Name = ''
SELECT RowNumber = ROW_NUMBER() OVER ( PARTITION BY T.[Name] ORDER BY T.[Name], C.column_id ) ,
SCHEMA_NAME(T.schema_id) AS SchemaName ,
T.[Name] AS Table_Name ,
C.[Name] AS Field_Name ,
sysType.name ,
C.max_length ,
C.is_nullable ,
C.is_identity ,
C.scale ,
C.precision
FROM Sys.Tables AS T
LEFT JOIN Sys.Columns AS C ON ( T.[Object_Id] = C.[Object_Id] )
LEFT JOIN sys.types AS sysType ON ( C.user_type_id = sysType.user_type_id )
WHERE ( Type = 'U' )
AND ( C.Name LIKE '%' + #Column_Name + '%' )
AND ( T.Name LIKE '%' + #Table_Name + '%' )
ORDER BY T.[Name] ,
C.column_id
This worked for SQL Server 2005, 2008, and 2012.
I found that the sys.identity_columns did not contain all my tables with identity columns.
SELECT a.name AS TableName, b.name AS IdentityColumn
FROM sys.sysobjects a
JOIN sys.syscolumns b
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;
Looking at the documentation page the status column can also be utilized. Also you can add the four part identifier and it will work across different servers.
SELECT a.name AS TableName, b.name AS IdentityColumn
FROM [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.sysobjects a
JOIN [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.syscolumns b
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;
Source:
https://msdn.microsoft.com/en-us/library/ms186816.aspx
By some reason sql server save some identity columns in different tables, the code that work for me, is the following:
select TABLE_NAME tabla,COLUMN_NAME columna
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
union all
select o.name tabla, c.name columna
from sys.objects o
inner join sys.columns c on o.object_id = c.object_id
where c.is_identity = 1
Get all columns with Identity. Modern version for MSSQL 2017+. Locks down to specific database:
SELECT
[COLUMN_NAME]
, [TABLE_NAME]
, [TABLE_CATALOG]
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
COLUMNPROPERTY(OBJECT_ID(CONCAT_WS('.' ,[TABLE_CATALOG] ,[TABLE_SCHEMA] ,[TABLE_NAME])) ,[COLUMN_NAME] ,'IsIdentity') = 1
ORDER BY
[TABLE_NAME]