Get Column Info for a Table or View in SQL Server (T-SQL: sp_columns)

In SQL Server you can use the sp_columns system stored procedure to return column information for the specified objects that can be queried in the current environment. Such a objects include tables, views, or other objects that have columns such as table-valued functions.

You can get information for a specific column, or you can specify all columns from a given table, view, etc.

Syntax

The syntax goes like this:

sp_columns [ @table_name = ] object  
     [ , [ @table_owner = ] owner ]   
     [ , [ @table_qualifier = ] qualifier ]   
     [ , [ @column_name = ] column ]   
     [ , [ @ODBCVer = ] ODBCVer ]

The @table_name argument is the only required argument. This is the name of the table/object that you want the column information from.

The other arguments are optional. For more information on these arguments, see the Microsoft documentation.

This stored procedure requires SELECT and VIEW DEFINITION permissions on the schema.

Example 1 – Return Information for a Specific Column

This example uses all possible arguments. It returns information for a specific column, in a specific table, from a specific table owner, in a specific database.

EXEC sp_columns
  @table_name = 'Cities', 
  @table_owner = 'Application',   
  @table_qualifier = 'WideWorldImporters',   
  @column_name = 'Location',
  @ODBCVer = 2;

Result (using vertical output):

TABLE_QUALIFIER   | WideWorldImporters
TABLE_OWNER       | Application
TABLE_NAME        | Cities
COLUMN_NAME       | Location
DATA_TYPE         | -4
TYPE_NAME         | geography
PRECISION         | 2147483647
LENGTH            | 2147483647
SCALE             | NULL
RADIX             | NULL
NULLABLE          | 1
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | -4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | 2147483647
ORDINAL_POSITION  | 4
IS_NULLABLE       | YES
SS_DATA_TYPE      | 23
(1 row affected)

Here’s a more concise way of doing it:

EXEC sp_columns
  'Cities', 
  'Application',   
  'WideWorldImporters',   
  'Location',
  2;

That returns the same results.

Example 2 – Specify a Table Only

In this example I switch to another database and only specify the table name.

USE Music;
EXEC sp_columns @table_name = 'Artists';

Result (using vertical output):

Changed database context to 'Music'.
-[ RECORD 1 ]-------------------------
TABLE_QUALIFIER   | Music
TABLE_OWNER       | dbo
TABLE_NAME        | Artists
COLUMN_NAME       | ArtistId
DATA_TYPE         | 4
TYPE_NAME         | int identity
PRECISION         | 10
LENGTH            | 4
SCALE             | 0
RADIX             | 10
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | 4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 1
IS_NULLABLE       | NO
SS_DATA_TYPE      | 56
-[ RECORD 2 ]-------------------------
TABLE_QUALIFIER   | Music
TABLE_OWNER       | dbo
TABLE_NAME        | Artists
COLUMN_NAME       | ArtistName
DATA_TYPE         | -9
TYPE_NAME         | nvarchar
PRECISION         | 255
LENGTH            | 510
SCALE             | NULL
RADIX             | NULL
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | -9
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | 510
ORDINAL_POSITION  | 2
IS_NULLABLE       | NO
SS_DATA_TYPE      | 39
-[ RECORD 3 ]-------------------------
TABLE_QUALIFIER   | Music
TABLE_OWNER       | dbo
TABLE_NAME        | Artists
COLUMN_NAME       | ActiveFrom
DATA_TYPE         | -9
TYPE_NAME         | date
PRECISION         | 10
LENGTH            | 20
SCALE             | NULL
RADIX             | NULL
NULLABLE          | 1
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | -9
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 3
IS_NULLABLE       | YES
SS_DATA_TYPE      | 0
(3 rows affected)

This returns information for all columns in the specified table.

You do need to be in the correct database though. If I re-run the previous example on a different database, I get no results.

USE WideWorldImporters;
EXEC sp_columns @table_name = 'Artists';

Result:

Changed database context to 'WideWorldImporters'.
(0 rows affected)

Example 3 – About the Table Qualifier

If you provide the @table_qualifier argument, it must be the same as the current database. If it’s not, an error is returned.

USE Music;
EXEC sp_columns
  @table_name = 'Artists',
  @table_qualifier = 'WideWorldImporters';

Results:

Msg 15250, Level 16, State 1, Line 24
The database name component of the object qualifier must be the name of the current database.

In this example I switched to the “Music” database, but then used a table qualifier of “WideWorldImporters”, which resulted in error Msg 15250 being returned.

In this case, I should have used a table qualifier of “Music”. Alternatively, I could have omitted the argument altogether.

Example 4 – Views

The syntax is the same, regardless of the object type. Here’s an example of getting column information for a view:

EXEC sp_columns
  @table_name = 'Customers',
  @table_owner = 'Website',
  @column_name = 'CustomerID'; 

Results:

TABLE_QUALIFIER   | WideWorldImporters
TABLE_OWNER       | Website
TABLE_NAME        | Customers
COLUMN_NAME       | CustomerID
DATA_TYPE         | 4
TYPE_NAME         | int
PRECISION         | 10
LENGTH            | 4
SCALE             | 0
RADIX             | 10
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | 4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 1
IS_NULLABLE       | NO
SS_DATA_TYPE      | 56

That happens to be column information for a view.

In this case, if I omit the table owner from the query, two rows are returned:

EXEC sp_columns
  @table_name = 'Customers',
  @column_name = 'CustomerID'; 

Results:

-[ RECORD 1 ]-------------------------
TABLE_QUALIFIER   | WideWorldImporters
TABLE_OWNER       | Sales
TABLE_NAME        | Customers
COLUMN_NAME       | CustomerID
DATA_TYPE         | 4
TYPE_NAME         | int
PRECISION         | 10
LENGTH            | 4
SCALE             | 0
RADIX             | 10
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | (NEXT VALUE FOR [Sequences].[CustomerID])
SQL_DATA_TYPE     | 4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 1
IS_NULLABLE       | NO
SS_DATA_TYPE      | 56
-[ RECORD 2 ]-------------------------
TABLE_QUALIFIER   | WideWorldImporters
TABLE_OWNER       | Website
TABLE_NAME        | Customers
COLUMN_NAME       | CustomerID
DATA_TYPE         | 4
TYPE_NAME         | int
PRECISION         | 10
LENGTH            | 4
SCALE             | 0
RADIX             | 10
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | 4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 1
IS_NULLABLE       | NO
SS_DATA_TYPE      | 56
(2 rows affected)

Two rows are returned because there are two objects called “Customers”. One is a view and the other is a table. The table owner for the view is called “Website”, and table owner for the table is called “Sales”.

Example 5 – Table-Valued Functions

As mentioned, you can also get column information for a table-valued function.

Here’s an example of getting column information for a table-valued function. Once again, the syntax is the same.

EXEC sp_columns
  @table_name = 'DetermineCustomerAccess'; 

Results:

TABLE_QUALIFIER   | WideWorldImporters
TABLE_OWNER       | Application
TABLE_NAME        | DetermineCustomerAccess
COLUMN_NAME       | AccessResult
DATA_TYPE         | 4
TYPE_NAME         | int
PRECISION         | 10
LENGTH            | 4
SCALE             | 0
RADIX             | 10
NULLABLE          | 0
REMARKS           | NULL
COLUMN_DEF        | NULL
SQL_DATA_TYPE     | 4
SQL_DATETIME_SUB  | NULL
CHAR_OCTET_LENGTH | NULL
ORDINAL_POSITION  | 1
IS_NULLABLE       | NO
SS_DATA_TYPE      | 56