A query to determine if a column is computed [duplicate] - sql

Would any of you know how to get the list of computed columns in a SQL Server database table?
I found sys.sp_help tablename does return this information, but only in the second result-set.
I am trying to find out if there is a better way of doing this. Something which only returns a single result set.

Check the sys.columns system catalog view:
SELECT *
FROM sys.columns
WHERE is_computed = 1
This gives you all computed columns in this database.
If you want those for just a single table, use this query:
SELECT *
FROM sys.columns
WHERE is_computed = 1
AND object_id = OBJECT_ID('YourTableName')
This works on SQL Server 2005 and up.
UPDATE: There's even a sys.computed_columns system catalog view which also contains the definition (expression) of the computed column - just in case that might be needed some time.
SELECT *
FROM sys.computed_columns
WHERE object_id = OBJECT_ID('YourTableName')

If you want to use the INFORMATION_SCHEMA views, then try
SELECT
COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed')
AS IS_COMPUTED,
*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='<Insert Your Table Name Here>'

For SQL Server 2000 the syntax is:
SELECT * FROM sys.columns
WHERE is_computed = 1
And the slightly more useful:
SELECT
sysobjects.name AS TableName,
syscolumns.name AS ColumnName
FROM syscolumns
INNER JOIN sysobjects
ON syscolumns.id = sysobjects.id
AND sysobjects.xtype = 'U' --User Tables
WHERE syscolumns.iscomputed = 1
sample output:
TableName ColumnName
===================== ==========
BrinksShipmentDetails Total
AdjustmentDetails Total
SoftCountDropDetails Total
CloserDetails Total
OpenerDetails Total
TransferDetails Total
(6 row(s) affected)

If you have many tables with computed columns and want to see the table names as well:
SELECT sys.objects.name, sys.computed_columns.name
from sys.computed_columns
inner join sys.objects on sys.objects.object_id = sys.computed_columns.object_id
order by sys.objects.name

Related

How to get the min value of a column after selecting it. Cannot perform an aggregate function on a column

My error is in this part (select min(sc.name) from so.name ), how to solve it ?
In the select I am getting the table and column name, in the same time i want to get the min value of the column from the table. Is that possible?.
select so.name table_name , sc.name Column_name,(select min(sc.name) from so.name )
from sysindexes si, syscolumns sc, sysobjects so
where si.indid < 2 -- 0 = if a table. 1 = if a clustered index on an allpages-locked table. >1 = if a nonclustered index or a clustered index on a data-only-locked table.
and so.type = 'U' --U – user table
and sc.status & 128 = 128 --(value 128) – indicates an identity column.
and so.id = sc.id
and so.id = si.id
So the problem is that You are trying to basically trying to do dynamic code where You try to select a column based on a table name from a system table.
Problem is that SQL doesnt know that the 'so.name' you are referencing is a table (further more, sysobjects also contains procedures and functions).
Rather than that, you should do an Inner join between sys.syscolumns and sys.systables based on object_id.

Getting the decriptions of the tables and columns via a sql statement

I have a database and a lot of tables inside it. I wrote some information into the each table and column's decription part. And now using query i want to see all table and columns descriptions.
Note: DATABASE -> ms sql server
Can you please help me ?
You can see that using INFORMATION_SCHEMA
To get columns for each table you can do:
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
To get table information you can do:
SELECT * FROM INFORMATION_SCHEMA.TABLES
Check this query:
SELECT
t.name AS TableName
, td.value AS TableDescription
, c.name AS ColumnName
, cd.value AS ColumnDescription
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
LEFT JOIN sys.extended_properties td
ON td.major_id = t.object_id
AND td.minor_id = 0
AND td.name = 'MS_Description'
LEFT JOIN sys.extended_properties cd
ON cd.major_id = t.object_id
AND cd.minor_id = c.column_id
AND cd.name = 'MS_Description'
select * from INFORMATION_SCHEMA.TABLES
select * from INFORMATION_SCHEMA.COLUMNS
select * from user_col_comments;
This will display all tables's column with comments for the logged in user.
select * from user_col_comments where table_name = '<table name>';
This will display specified tables's column with comments for the logged in user.
desc table_name query is used to describe the table

Find the real column name of an alias used in a view?

Suppose I have a view in which some of the column names are aliases, like "surName" in this example:
CREATE VIEW myView AS
SELECT
firstName,
middleName,
you.lastName surName
FROM
myTable me
LEFT OUTER JOIN yourTable you
ON me.code = you.code
GO
I'm able to retrieve some information about the view using the INFORMATION_SCHEMA views.
For example, the query
SELECT column_name AS ALIAS, data_type AS TYPE
FROM information_schema.columns
WHERE table_name = 'myView'
yields:
----------------
|ALIAS |TYPE |
----------------
|firstName |nchar|
|middleName|nchar|
|surName |nchar|
----------------
However, I would like to know the actual column name as well. Ideally:
---------------------------
|ALIAS |TYPE |REALNAME |
---------------------------
|firstName |nchar|firstName |
|middleName|nchar|middleName|
|surName |nchar|lastName |
---------------------------
How can I determine what the real column name is based on the alias? There must be some way to use the sys tables and/or INFORMATION_SCHEMA views to retrieve this information.
EDIT:
I can get close with this abomination, which is similar to Arion's answer:
SELECT
c.name AS ALIAS,
ISNULL(type_name(c.system_type_id), t.name) AS DATA_TYPE,
tablecols.name AS REALNAME
FROM
sys.views v
JOIN sys.columns c ON c.object_id = v.object_id
LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.sql_dependencies d ON d.object_id = v.object_id
AND c.column_id = d.referenced_minor_id
JOIN sys.columns tablecols ON d.referenced_major_id = tablecols.object_id
AND tablecols.column_id = d.referenced_minor_id
AND tablecols.column_id = c.column_id
WHERE v.name ='myView'
This yields:
---------------------------
|ALIAS |TYPE |REALNAME |
---------------------------
|firstName |nchar|firstName |
|middleName|nchar|middleName|
|surName |nchar|code |
|surName |nchar|lastName |
---------------------------
but the third record is wrong -- this happens with any view created using a "JOIN" clause, because there are two columns with the same "column_id", but in different tables.
Given this view:
CREATE VIEW viewTest
AS
SELECT
books.id,
books.author,
Books.title AS Name
FROM
Books
What I can see you can get the columns used and the tables used by doing this:
SELECT *
FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE AS UsedColumns
WHERE UsedColumns.VIEW_NAME='viewTest'
SELECT *
FROM INFORMATION_SCHEMA.VIEW_TABLE_USAGE AS UsedTables
WHERE UsedTables.VIEW_NAME='viewTest'
This is for sql server 2005+. See reference here
Edit
Give the same view. Try this query:
SELECT
c.name AS columnName,
columnTypes.name as dataType,
aliases.name as alias
FROM
sys.views v
JOIN sys.sql_dependencies d
ON d.object_id = v.object_id
JOIN .sys.objects t
ON t.object_id = d.referenced_major_id
JOIN sys.columns c
ON c.object_id = d.referenced_major_id
JOIN sys.types AS columnTypes
ON c.user_type_id=columnTypes.user_type_id
AND c.column_id = d.referenced_minor_id
JOIN sys.columns AS aliases
on c.column_id=aliases.column_id
AND aliases.object_id = object_id('viewTest')
WHERE
v.name = 'viewTest';
It returns this for me:
columnName dataType alias
id int id
author varchar author
title varchar Name
This is also tested in sql 2005+
Having spent a number of hours trying to find an answer to this, and repeatedly running into solutions that didn't work and posters that appeared to eventually give up, I eventually stumbled across an answer here that appears to work:
https://social.msdn.microsoft.com/Forums/windowsserver/en-US/afa2ed2b-62de-4a5e-ae70-942e75f887a1/find-out-original-columns-name-when-used-in-a-view-with-alias?forum=transactsql
The following SQL returns, I believe, exactly what you're looking for, it's certainly doing what I need and appears to perform well too.
SELECT name
, source_database
, source_schema
, source_table
, source_column
, system_type_name
, is_identity_column
FROM sys.dm_exec_describe_first_result_set (N'SELECT * from ViewName', null, 1)
Documentation on the sys.dm_exec_describe_first_result_set function can be found here, it's available in SQL Server 2012 and later:
https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-describe-first-result-set-transact-sql
Full credit to the poster on the link, I didn't work this out myself, but I wanted to post this here in case it's useful to anyone else searching for this information as I found this thread much more easily than the one I linked to.
I think you can't.
Select query hides actual data source it was performed against. Because you can query anything, i.e. view, table, even linked remote server.
Not a Perfect solution; but, it is possible to parse the view_definition with a high degree of accuracy especially if the code is well organized with consistent aliasing by 'as'. Additionally, one can parse for a comma ',' after the alias.
Of note: the final field in the select clause will not have the comma and I was unable to exclude items being used as comments (for example interlaced in the view text with --)
I wrote the below for a table named 'My_Table' and view correspondingly called 'vMy_Table'
select alias, t.COLUMN_name
from
(
select VC.COLUMN_NAME,
case when
ROW_NUMBER () OVER (
partition by C.COLUMN_NAME order by
CHARINDEX(',',VIEW_DEFINITION,CHARINDEX(C.COLUMN_NAME,VIEW_DEFINITION))-
CHARINDEX(VC.COLUMN_NAME,VIEW_DEFINITION)
) = 1
then 1
else 0 end
as lenDiff
,C.COLUMN_NAME as alias
,CHARINDEX(',',VIEW_DEFINITION,CHARINDEX(C.COLUMN_NAME,VIEW_DEFINITION)) diff1
, CHARINDEX(VC.COLUMN_NAME,VIEW_DEFINITION) diff2
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE VC
inner join INFORMATION_SCHEMA.VIEWS V on V.TABLE_NAME = 'v'+VC.TABLE_Name
inner join information_schema.COLUMNS C on C.TABLE_NAME = 'v'+VC.TABLE_Name
where VC.TABLE_NAME = 'My_Table'
and CHARINDEX(',',VIEW_DEFINITION,CHARINDEX(C.COLUMN_NAME,VIEW_DEFINITION))-
CHARINDEX(VC.COLUMN_NAME,VIEW_DEFINITION) >0
)
t
where lenDiff = 1
Hope this helps and I look forward to your feedback

How to get column metadata from a table synonym

How can I determine column metadata from a table synonym in a SQL Server 2005 database? I have a synonym called 'ProjectSyn' for a table called 'Project', but I can find no column metadata for the synonym.
My guess is to somewhere determine the 'base table' for the synonym, then query for column metadata for that table. Is this a correct approach, and if not, what would be?
This is my solution which works with synonyms of different databases:
SELECT TOP 0 * INTO #TEMP1 FROM YourTable
SELECT
[column_name] = c.name,
[data_type] = t.name,
[character_maximum_length] = c.max_length
FROM tempdb.sys.columns c
inner join tempdb.sys.types t on t.system_type_id = c.system_type_id
WHERE [object_id] = object_id('tempdb..#TEMP1');
DROP TABLE #TEMP1
Something like this? (edited)
select c.*
from
sys.columns c
inner join sys.synonyms s on c.object_id = object_id(s.base_object_name)
where
s.name = 'ProjectSyn'
Yes, I think getting the base object and then retrieve the columns, is your only option.
To get the base object name for a synonym, just query the view sys.synonyms

Get List of Computed Columns in Database Table (SQL Server)

Would any of you know how to get the list of computed columns in a SQL Server database table?
I found sys.sp_help tablename does return this information, but only in the second result-set.
I am trying to find out if there is a better way of doing this. Something which only returns a single result set.
Check the sys.columns system catalog view:
SELECT *
FROM sys.columns
WHERE is_computed = 1
This gives you all computed columns in this database.
If you want those for just a single table, use this query:
SELECT *
FROM sys.columns
WHERE is_computed = 1
AND object_id = OBJECT_ID('YourTableName')
This works on SQL Server 2005 and up.
UPDATE: There's even a sys.computed_columns system catalog view which also contains the definition (expression) of the computed column - just in case that might be needed some time.
SELECT *
FROM sys.computed_columns
WHERE object_id = OBJECT_ID('YourTableName')
If you want to use the INFORMATION_SCHEMA views, then try
SELECT
COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed')
AS IS_COMPUTED,
*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='<Insert Your Table Name Here>'
For SQL Server 2000 the syntax is:
SELECT * FROM sys.columns
WHERE is_computed = 1
And the slightly more useful:
SELECT
sysobjects.name AS TableName,
syscolumns.name AS ColumnName
FROM syscolumns
INNER JOIN sysobjects
ON syscolumns.id = sysobjects.id
AND sysobjects.xtype = 'U' --User Tables
WHERE syscolumns.iscomputed = 1
sample output:
TableName ColumnName
===================== ==========
BrinksShipmentDetails Total
AdjustmentDetails Total
SoftCountDropDetails Total
CloserDetails Total
OpenerDetails Total
TransferDetails Total
(6 row(s) affected)
If you have many tables with computed columns and want to see the table names as well:
SELECT sys.objects.name, sys.computed_columns.name
from sys.computed_columns
inner join sys.objects on sys.objects.object_id = sys.computed_columns.object_id
order by sys.objects.name