Generate **bare** CREATE TABLE and CREATE PROC statemnts in SQL Server - sql-server

The deployment procedures in my company require that SQL scripts for creation of procedures and tables, etc. be bare.
Generating create scripts in SQL Server Management Studio gives you significantly more than a bare script, which is unfortunate in this case. For example, for a test table this is what SSMS generated for me:
USE [DemoDB]
GO
/****** Object: Table [dbo].[example] Script Date: 08/07/2012 15:46:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[example](
[fake_row] [int] NULL
) ON [PRIMARY]
GO
So, what I'd like to know is:
Can I somehow run a query on SQL Server in SSMS that would give me a script that was literally just the following?
create table example (
fake_row int
)

You can create your own "create table" statements, using information_schema (Aaron . . . I know, INFORMATION_SCHEMA ;).
I have written some code for this purpose, but it doesn't use INFORMATION_SCHEMA. I know, if uses older system tables that are probably scheduled to be removed. It also adds in some additional information (which you can remove, since you don't need it). Just put the list of tables in the #INCLUSIONLIST and run this in the database where the tables reside.
SET #INCLUSIONLIST = '|table1|table2|';
SELECT (CASE WHEN rownum = 1 THEN 'CREATE TABLE ['+a.t_name+'] ('
WHEN c.column_id IS NOT NULL
THEN ' ['+c.c_name+'] ' +
(CASE WHEN CHARINDEX('CHAR', datatype) > 0 THEN datatype+'('+(case when length < 0 then 'max' else cast(length as varchar) end)+')'
WHEN CHARINDEX('BINARY', datatype) > 0 THEN datatype+'('+cast(length as varchar)+')'
WHEN datatype = 'float' AND precision <> 24 THEN datatype+'('+cast(precision as varchar)+')'
WHEN datatype IN ('numeric', 'decimal') AND scale = 0 THEN datatype+'('+cast(precision as varchar)+')'
WHEN datatype IN ('numeric', 'decimal') AND scale > 0 THEN datatype+'('+cast(precision as varchar)+','+cast(scale as varchar)+')'
ELSE datatype END)+' '+
(CASE WHEN c.identity_seed IS NOT NULL
THEN 'IDENTITY(' + CAST(identity_seed AS VARCHAR) + ',' + CAST(identity_increment AS VARCHAR) + ') '
ELSE '' END) +
(CASE WHEN c.is_nullable = 0 THEN 'NOT NULL ' ELSE '' END) +
(CASE WHEN c.default_definition IS NOT NULL
THEN 'DEFAULT '+default_definition ELSE '' END) +
(CASE WHEN max_column_id = column_id AND pk.pk_name IS NULL THEN '' ELSE ',' END)
WHEN rownum = max_column_id + 2 and pk.pk_name IS NOT NULL
THEN ' PRIMARY KEY ('+pk.pk_columns+')'
WHEN rownum = max_column_id + 3 THEN ') /* CREATE TABLE '+a.t_name+' */'
WHEN rownum = max_column_id + 4 THEN 'GO'
WHEN rownum = max_column_id + 5 THEN ''
END)
FROM (SELECT t.t_name, rownum, max_column_id
FROM (SELECT t.name as t_name, MAX(c.column_id) as max_column_id
FROM sys.columns c join
(SELECT * FROM sys.tables WHERE CHARINDEX('|'+name+'|', #INCLUSIONLIST) > 0 ) t
ON c.object_id = t.object_id
GROUP BY t.name) t join
(SELECT ROW_NUMBER() OVER (ORDER BY object_id) as rownum FROM sys.columns c) ctr
ON ctr.rownum <= t.max_column_id + 5
) a LEFT OUTER JOIN
(SELECT t.name as t_name, c.column_id, c.name AS c_name, u.name as datatype,
ISNULL(baset.name, N'') AS systemtype,
CAST(CASE WHEN baset.name IN (N'nchar', N'nvarchar') AND c.max_length <> -1
THEN c.max_length/2 ELSE c.max_length END AS INT) AS length,
c.precision AS precision,
c.scale as scale,
c.is_nullable,
dc.definition as default_definition,
idc.seed_value as identity_seed, idc.increment_value as identity_increment
FROM sys.tables t JOIN
sys.all_columns AS c
ON c.object_id = t.object_id LEFT OUTER JOIN
sys.types u
ON u.user_type_id = c.user_type_id LEFT OUTER JOIN
sys.types baset
ON baset.user_type_id = c.system_type_id AND
baset.user_type_id = baset.system_type_id LEFT OUTER JOIN
sys.default_constraints dc
ON c.object_id = dc.parent_object_id AND
c.column_id = dc.parent_column_id LEFT OUTER JOIN
sys.identity_columns idc
ON c.object_id = idc.object_id AND
c.column_id = idc.column_id
) c
ON a.t_name = c.t_name AND
c.column_id + 1 = a.rownum LEFT OUTER JOIN
(SELECT t.name as t_name, kc.name as pk_name,
(MAX(CASE WHEN index_column_id = 1 THEN '['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 2 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 3 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 4 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 5 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 6 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 7 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 8 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 9 THEN ','+'['+c.name+']' ELSE '' END) +
MAX(CASE WHEN index_column_id = 10 THEN ','+'['+c.name+']' ELSE '' END)
) as pk_columns
FROM sys.indexes i JOIN
sys.key_constraints kc
ON i.name = kc.name AND
kc.type = 'PK' JOIN
sys.tables t
ON i.object_id = t.object_id 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.index_column_id = c.column_id AND
ic.object_id = c.object_id
GROUP BY t.name, kc.name
) pk
ON pk.t_name = a.t_name
ORDER BY a.t_name, rownum

Apologies for the self-answer, marking other good answers +1.
It turns out you can get pretty much all of the way there with utility in SSMS.
Right click on the database in the object explorer
Click "Tasks"
Click "Generate Scripts"
Select "Script Specific Objects" and choose tables, or whatever else
Select "Save To File" & "Single File Per Object" (or just spool to query window)
Click "Advanced" and you can enable/disable the generation of virtually every part of the statements you're generating including constraints, use statements, etc.
If further removal is required (e.g. removing GO), it's minimal

Optionally, you can control the general scripting behavior of SSMS like so: Options for scripting SQL Server database objects.

I would create stored procs that read from the INFORMATION_SCHEMA views.
Getting the stored proc text is just:
DECLARE #SQL VARCHAR(8000)
SET #SQL=' '
select #SQL = #SQL + ROUTINE_DEFINITION
from INFORMATION_SCHEMA.ROUTINES
where ROUTINE_TYPE='PROCEDURE'
AND SPECIFIC_NAME = 'updateComments'
PRINT #SQL
The one to script the table would looks something like:
DECLARE #tableName VARCHAR(50)
SET #tableName = 'Location'
-- Need to know how many columns
DECLARE #NumColumns int
SELECT #NumColumns = MAX(ORDINAL_POSITION)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tableName
DECLARE #SQL VARCHAR(8000)
SET #SQL=' '
DECLARE #Results TABLE
(LineNumber int,
Line VARCHAR(1000))
INSERT INTO #Results
SELECT 0 AS ORDINAL_POSITION,
'CREATE TABLE '+TABLE_SCHEMA+'.'+#tableName+' (' AS Line
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #tableName
UNION ALL
SELECT ORDINAL_POSITION,
'['+COLUMN_NAME+'] '+ DATA_TYPE +
CASE WHEN DATA_TYPE = 'varchar' OR DATA_TYPE = 'char'
THEN '('+ CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) +')'
ELSE '' END +
CASE WHEN IS_NULLABLE = 'NO'
THEN ' NULL '
ELSE ' NOT NULL' END +
CASE WHEN ORDINAL_POSITION < #NumColumns
THEN ', '
ELSE ' ' END
AS LINE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tableName
UNION ALL
SELECT 999, ' )'
SELECT Line
FROM #Results
ORDER BY LineNumber
SELECT #SQL = #SQL + Line
FROM #Results
ORDER BY LineNumber
SELECT #SQL
PRINT #SQL
This creates the simple table script that you want, but it is not complete - doesn't do numeric precision, primary key, etc. But this is enough to get you started.
I would just make each one of these into a stored proc that takes the object name as a parameter.

Related

How to Show the Correct Column Name and Data Type in T-SQL?

I produced DDLs to create tables on Oracle using T-SQL since my source tables are in SQL Server. While I was using only 4 tables for testing, it produced 4 DDLs but it repeated the name of the last column and the data type of the table even though The number of columns is correct.
For example, TABLE_01 has 6 columns and it repeats the last column name and data type for 6 times.
CREATE TABLE TABLE_01(
ISKEY INT
ISKEY INT
ISKEY INT
ISKEY INT
ISKEY INT
ISKEY INT
);
Here is my code. Does anyone find the reason why it repeats them? I couldn't find the cause.
Please help me to solve this problem. I would appreciate your taking time and sharing knowledge for me.
DECLARE #MyList TABLE (Value NVARCHAR(50))
INSERT INTO #MyList VALUES ('TABLE_01')
INSERT INTO #MyList VALUES ('TABLE_02')
INSERT INTO #MyList VALUES ('TABLE_03')
INSERT INTO #MyList VALUES ('TABLE_04')
DECLARE #VALUE VARCHAR(50)
DECLARE #COLNAME VARCHAR(50) = ''
DECLARE #COLTYPE VARCHAR(50) = ''
DECLARE #COLNUM INT = 0
DECLARE #COL_COUNTER INT = 0
DECLARE #COUNTER INT = 0;
DECLARE #MAX INT = (SELECT COUNT(*) FROM #MyList)
-- Loop for Multiple Tables
WHILE #COUNTER < #MAX
BEGIN
SET #VALUE = (SELECT VALUE FROM
(SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) [index] , Value from #MyList) R
ORDER BY R.[index] OFFSET #COUNTER
ROWS FETCH NEXT 1 ROWS ONLY);
SELECT CONCAT('CREATE TABLE ' , REPLACE(UPPER(#VALUE), '_',''), '(')
PRINT 'CREATE TABLE ' + REPLACE(UPPER(#VALUE), '_','') + '('
SET #COLNUM = 0
SET #COL_COUNTER = 0
;WITH numcol AS
(
select schema_name(tab.schema_id) as schema_name,
tab.name as table_name,
col.column_id,
col.name as column_name,
t.name as data_type,
col.max_length,
col.precision
from sys.tables as tab
inner join sys.columns as col
on tab.object_id = col.object_id
left join sys.types as t
on col.user_type_id = t.user_type_id
where schema_name(tab.schema_id) = 'dbo' AND tab.name = #VALUE
)
SELECT #COLNUM = COUNT(*) OVER (PARTITION BY schema_name, table_name) FROM numcol
-- Loop for Multiple Columns
WHILE #COL_COUNTER < #COLNUM
BEGIN
SET #COLNAME = ''
SET #COLTYPE = ''
SELECT #COLNAME = REPLACE(UPPER(COL.name), '_',''), #COLTYPE = CASE WHEN UPPER(col_type.name) = 'MONEY' THEN ' ' +' NUMBER(19,4)'
WHEN UPPER(col_type.name) = 'REAL' THEN ' ' +' FLOAT(23)'
WHEN UPPER(col_type.name) = 'FLOAT' THEN ' ' +' FLOAT(49)'
WHEN UPPER(col_type.name) = 'NVARCHAR' THEN ' ' +' NCHAR'
ELSE ' ' + UPPER(col_type.name)
END
FROM sys.columns COL
INNER JOIN sys.tables TAB
On COL.object_id = TAB.object_id
left join sys.types as col_type
on col.user_type_id = col_type.user_type_id
WHERE OBJECT_NAME(TAB.object_id) = #VALUE
PRINT #COLNAME + #COLTYPE
SET #COL_COUNTER = #COL_COUNTER + 1
END
PRINT ');'
SET #COUNTER = #COUNTER + 1
END
Thank you.
That' a really horrible way to create an SQL script. It's effectively a cursor, and more difficult to write, it's also completely unnecessary.
You can just build the whole thing in one go using STRING_AGG.
I make no comment on the validity of the result for Oracle, as I don't know Oracle well enough.
DECLARE #table sysname = 'YourTable';
DECLARE #schema sysname = 'dbo';
DECLARE #columns nvarchar(max);
SELECT #columns = STRING_AGG(CONCAT(
' '
REPLACE(UPPER(col.name), '_', ''),
' ',
CASE UPPER(col_type.name)
WHEN 'MONEY' THEN ' NUMBER(19,4)'
WHEN 'REAL' THEN ' FLOAT(23)'
WHEN 'FLOAT' THEN ' FLOAT(49)'
WHEN 'NVARCHAR' THEN ' NCHAR'
ELSE UPPER(col_type.name)
END,
), ',
')
FROM sys.columns col
INNER JOIN sys.tables tab ON col.object_id = tab.object_id
JOIN sys.types as col_type ON col.user_type_id = col_type.user_type_id
JOIN sys.schemas sch ON sch.schema_id = tab.schema_id
WHERE tab.name = #table
AND sch.name = #schema;
SELECT
CONCAT(
'CREATE TABLE ',
REPLACE(UPPER(#table), '_',''),
' (
',
#columns,
'
)'
);

Inserting records from a table to another using dynamic SQL with conditions to convert data type

I have two tables whose structures as follows:
table_A
CREATE TABLE table_A
(
col_a varchar(100),
col_b bigint,
col_c datetime
)
table_b
--Note that columns are same--
CREATE TABLE table_B
(
col_a varchar(10),
col_b varchar(10),
col_c varchar(20)
)
Now I want to INSERT data into table_A from table_B with proper data type conversion.
Below is the SQL string:
INSERT INTO table_A(col_a,col_b,col_c)
SELECT CONVERT(varchar,col_a),CONVERT(INT,col_b),CONVERT(datetime,col_c) FROM table_B
So far so good.
Now I want generate the SQL dynamically with the help of INFORMATION_SCHEMA.COLUMNS.
For this I have followed the below steps:
Step 1:
Join the Information Schema for the above two tables viz table_A and table_B and store them in a #TempTable. Lets assume that #TempTable has an ID column that is IDENTITY(1,1) but that doesn't follow any sequence like 1,2,3...(Typically this happens in Synapse SQL)
INSERT INTO #TempTable
SELECT S.COLUMN_NAME AS Src_Col,
S.DATA_TYPE AS Src_dtype,
D.COLUMN_NAME AS Dest_Col,
D.DATA_TYPE AS Dest_dtype,
CASE WHEN S.DATA_TYPE NOT LIKE D.DATA_TYPE THEN
'CONVERT('+ '''' + D.DATA_TYPE + '''' + ',' + '''' + S.DATA_TYPE + '''' + ')'
ELSE S.DATA_TYPE AS Modified_Col
FROM INFORMATION_SCHEMA S
JOIN INFORMATION_SCHEMA.COLUMNS D
ON S.COLUMN_NAME = D.COLUMN_NAME AND S.TABLE_NAME = REPLACE(D.TABLE_NAME,'_B','_A')
Step 2:
Iterate over #TempTable to fetch the Modified_Col values
SET #Max_ID = (SELECT MAX(ID) FROM #TempTable);
SET #Min_ID = (SELECT MIN(ID) FROM #TempTable);
SET #ColToInsert = '';
SET #Dest_Col = '';
WHILE #Min_ID <= #Max_ID
BEGIN
SET #ColToInsert = (SELECT #ColToInsert + Modified_Col FROM #TempTable T WHERE T.ID = #Min_ID);
SET #Dest_Col = (SELECT #Dest_Col + Dest_Col FROM #TempTable T WHERE T.ID = #Min_ID);
SET #Min_ID = #Min_ID + 1;
END
Step 3:
Use that #ColToInsert in the below Dynamic SQL
SET #DySQL = 'INSERT INTO Table_A(' + #Dest_Col + ') SELECT ' + #ColToInsert + ' FROM table_B';
exec (#DySQL);
Now at this step 3 I am not getting the expected result. No data is getting inserted into table_A. I can understand that in the CASE statement I have to make some fixes so that convert... portion becomes a string. And I am not able to do so.
Any clue would be appreciated.
I don't understand why you need the temp table at all. You just need to aggregate using STRING_AGG.
You also need to quote the objects and columns using QUOTENAME, and you should use sys.columns etc rather than INFORMATION_SCHEMA, which is for compatibility only.
DECLARE #tableA sysname = 't';
DECLARE #tableB sysname = 's';
DECLARE #sql nvarchar(max) = (
SELECT CONCAT(
'INSERT INTO ',
QUOTENAME(#tableA),
'(',
STRING_AGG(CAST(QUOTENAME(cA.name) AS nvarchar(max)), ', '),
')
SELECT ',
STRING_AGG(
CASE WHEN cA.user_type_id <> cB.user_type_id THEN
CONCAT(
'CONVERT(',
typ.name,
CASE
WHEN typ.name IN ('varchar','nvarchar','char','nchar','varbinary','binary')
THEN CONCAT('(', CASE WHEN cA.max_length = -1 THEN 'max' END, NULLIF(cA.max_length, -1), ')')
WHEN typ.name IN ('datetime2','datetimeoffset','time','float','real')
THEN CONCAT('(', cA.scale, ')')
WHEN typ.name IN ('float','real')
THEN CONCAT('(', cA.precision, ')')
WHEN typ.name IN ('decimal','numeric')
THEN CONCAT('(', cA.precision, ',', cA.scale, ')')
END,
', ',
CAST(QUOTENAME(cB.name) AS nvarchar(max)),
')'
)
ELSE
CAST(QUOTENAME(cB.name) AS nvarchar(max))
END
, ', '),
'
FROM ',
QUOTENAME(#tableB)
)
FROM sys.columns cA
JOIN sys.tables tA ON ta.object_id = cA.object_id AND tA.name = #tableA
JOIN sys.types typ ON typ.user_type_id = cA.user_type_id
JOIN sys.columns cB ON cB.name = cA.name
JOIN sys.tables tB ON tB.object_id = cB.object_id AND tB.name = #tableB
);
PRINT #sql; -- your friend
EXEC sp_executesql #sql;
db<>fiddle

How to find matching columns in multiple tables in a SQL Server database?

How to find matching columns in multiple tables in a SQL Server database?
I have a SQL Server database with over 30 tables, is there a way to filter and/or produce a list of the common columns amongst the tables rather than going through each manually?
Maybe some code?
As explained in the comments, you want to use system table sys.columns to achieve your goal.
This query lists all column names that are present more than once in the database, along with the number of occurences :
SELECT name, COUNT(*)
FROM sys.columns
GROUP BY name
HAVING COUNT(*) > 1
You can join the results with sys.tables to recover the corresponding tables, like :
SELECT
C.name AS ColumnName,
T.name AS TableName
FROM
(SELECT name FROM sys.columns GROUP BY name HAVING COUNT(*) > 1 ) A
JOIN sys.columns C on C.name = A.name
JOIN sys.tables T ON T.object_id = C.object_id
ORDER BY
C.name,
T.name
I'd use something easy like this:
SELECT [Unique name #] = DENSE_RANK() OVER(ORDER BY c.name)
, [Column] = c.name
, [Column type] = t.name
, [Column max length] = c.max_length
, [Column precision] = c.precision
, [Table schema] = OBJECT_SCHEMA_NAME(c.object_id)
, [Table name] = OBJECT_NAME(c.object_id)
FROM sys.columns as c
INNER JOIN sys.systypes as t ON t.type = c.system_type_id
WHERE OBJECTPROPERTY(c.object_id,'IsTable') = 1
and OBJECT_SCHEMA_NAME(c.object_id) != 'sys'
ORDER BY c.name;
With this query you have all the columns with same name in different tables of your DB:
select object_name(c.id) + '.' + c.name + ' '
+ t.name
+ case when t.xtype = t.xusertype then '' else '[' + tr.name end
+ case
when tr.name in ('bit', 'tinyint', 'smallint', 'int', 'bigint',
'float', 'money', 'smallmoney', 'real', 'date', 'time',
'datetime', 'datetime2', 'smalldatetime', 'timestamp')
then ''
else
case when isNull(c.prec,0)=0 then ''
else '('
+ case when c.prec = - 1 then 'MAX' else cast(c.prec as varchar) end
+ case when c.scale is null then '' else ',' + cast(c.scale as varchar) end
+ ')'
end
end
+ case when t.xtype = t.xusertype then '' else ']' end
+ case when t.collationId <> c.collationId
then ' collate ' + c.collation collate Latin1_General_BIN else '' end
+ case c.isnullable when 0 then ' not null' else '' end
+ case c.colstat
when 1 then ' identity(' + Cast(Ident_seed(o.name) as varchar)
+ ',' + cast(Ident_incr(o.name) as varchar) + ')'
else ''
end
+ case when cm.text is null then ''
else ' default '
+ case when patindex('% as %', cm.text) > 0
then rtrim(substring(cm.text, patindex('% as %', cm.text) + 4, len(cm.text)))
else substring(cm.text, 2, len(cm.text) - 2)
end
end
as Columns
from syscolumns c
join systypes t on (t.xusertype = c.xusertype)
left join systypes tr
on (tr.xtype = t.xtype and tr.xusertype = t.xtype)
join sysobjects o
on (o.id = c.id)
left join syscomments cm
on (cm.id = c.cdefault)
where c.name in (
select cl.name
from syscolumns cl
join sysobjects ob on (cl.id = ob.id and ob.xtype = 'U')
group by cl.name
having count(*) > 1
)
order by c.name
this will work:
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table1name'
intersect
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table2name';
intersect
...
...
..
...
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table30name';
sql server equivalent:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table1'
intersect
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table2'
intersect
.....
....
...
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table30';
Below is the query which will provide you the list of all tables where your "Column" is present.
SELECT c.name AS ColName, t.name AS TableName FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id WHERE c.name LIKE '%ColumnName%';
And based on that you can continue you task you want to perform.
Thumbs up if it is helpful.
select name as 'Column_Name' from syscolumns s1 where id = object_id('table1') and
exists(select 1 from syscolumns s2 where s2.name = s1.name and s2.id = object_id('table2'))
it will return the matched columns

How to check which columns in my database hold data dynamically

I am dealing with a problem that I need to make a sql query like this:
SELECT
SUM(CASE WHEN ID IS NOT NULL THEN 0 ELSE 1 END) AS column_ID_count,
SUM(CASE WHEN NAME IS NOT NULL THEN 0 ELSE 1 END) AS column_NAME_count,
SUM(CASE WHEN COMMENT IS NOT NULL THEN 1 ELSE 0 END) AS column_COMMENT_count
FROM
Table1
The problem is that I have more than 100 columns so making this query by hand will be a real pain. So I was thinking that there should be a way to select all column names and dump them to text file. The output would look like:
SUM(CASE WHEN NAME IS NOT NULL THEN 0 ELSE 1 END) AS column_NAME_count,
...
SUM(CASE WHEN COMMENT IS NOT NULL THEN 1 ELSE 0 END) AS column_COMMENT_count
I tried exec sp_help but that is not what I need. So is there a way to do this with a query?
This will give you column names for the table in question.
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'yourtablename'
If you want a list of all column names in your table then you want something like this;
DECLARE #TableName varchar(50); SET #TableName = 'TableName'
SELECT c.name
INTO #ColumnNames
FROM sys.columns c
JOIN sys.objects o
ON c.object_id = o.object_id
WHERE o.name = #TableName
SELECT * FROM #ColumnNames
Drop the results to a text file if that's what you want and you're done.
If you want a script to return all columns in your database and whether they contain data, you could use this;
SELECT 'SELECT count([' + c.name + ']) as Data_Count, ''' + o.name + '.' + c.name + ''' AS Table_Column FROM [' + o.name + '] UNION ALL '
FROM sys.columns c
JOIN sys.objects o
ON c.object_id = o.object_id
WHERE c.is_nullable = 1
AND o.type = 'U'
And paste the results into a new window. You'll have to remove the final UNION ALL and this won't work with text or ntext data types so if you have some of these you'll have to remove them. You could filter them out in the query but then you'd never know about them.
Edit: If you want to exclude the incompatible data types then use this query;
SELECT 'SELECT count([' + c.name + ']) as Data_Count, ''' + o.name + '.' + c.name + ''' AS Table_Column FROM [' + o.name + '] UNION ALL '
FROM sys.columns c
JOIN sys.objects o
ON c.object_id = o.object_id
JOIN sys.types t
ON c.user_type_id = t.user_type_id
WHERE c.is_nullable = 1
AND o.type = 'U'
AND t.name NOT IN ('image','text','ntext')
Just remember to check these data types with a different query so you don't miss them.
try this query
declare #cnmae nvarchar(max)='select '
SELECT #cnmae+= 'sum( case when ' + COLUMN_NAME +
' is not null then 0 else 1 end) as column_'+COLUMN_NAME+'_count,'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table1'
select #cnmae=stuff(#cnmae,len(#cnmae),1,'') + ' from Table1'
exec sp_executesql #cnmae

How do you determine what SQL Tables have an identity column programmatically

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]

Resources