In SQL Server 2012, how do I get the column name and data type from a view, function, or stored procedure? - sql

I am able to obtain column names and data types from a database table with:
SELECT COLUMN_NAME, DATA_TYPE
FROM information_schema.columns
WHERE TABLE_NAME = 'xxx'
How can I get the column name and data type from a view, function, or stored procedure? I imagine I'd have to obtain them using the results of each but I'm unsure.
Thanks for the help

Columns for view:
SELECT * FROM sys.columns c where c.object_id = OBJECT_ID('<schema>.<view name>')
Columns for table valued function:
SELECT * FROM INFORMATION_SCHEMA.ROUTINE_COLUMNS rc WHERE rc.TABLE_NAME = '<udf name>'
Columns for stored procedure
For SQL server 2012 and later:
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('<shcema>.<sp name>'),
NULL
);
Taken from Retrieve column names and types of a stored procedure?. Read answers there for possible ways to do this (for example with pre 2012).

Related

how can I print details (table name, column name, data type) of each column/table in my db2 database?

In my previous question Mark suggested a good answer for displaying count on every table in my database. I would like to expand this procedure and - instead of counts - display the specific info (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE) about each column in the database.
I so far have the following command:
--#SET TERMINATOR #
CREATE OR REPLACE FUNCTION EXPORT_SCHEMAS()
RETURNS TABLE (P_TABSCHEMA VARCHAR(128), P_TABNAME VARCHAR(128), P_COLUM_NNAME VARCHAR(128), P_DATA_TYPE VARCHAR(128))
BEGIN
DECLARE L_STMT VARCHAR(256);
DECLARE L_ROWS VARCHAR(256);
FOR V1 AS
SELECT TABSCHEMA, TABNAME
FROM SYSCAT.TABLES
WHERE TYPE = 'T'
ORDER BY 1,2
DO
SET L_STMT = 'SET ? = (SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM SYSIBM.COLUMNS where TABLE_NAME = "'||V1.TABNAME||'" AND TABLE_SCHEMA = "'||V1.TABSCHEMA||'")';
PREPARE S FROM L_STMT;
EXECUTE S INTO L_ROWS;
PIPE(L_ROWS);
END FOR;
RETURN;
END#
SELECT * FROM TABLE(EXPORT_SCHEMAS())#
but now when I run it:
db2 -ntd~ -f export_schemas.sql > dump.csv
I'm getting the error:
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL20019N The result type returned from the function body cannot be assigned
to the data type defined in the RETURNS clause. LINE NUMBER=17.
SQLSTATE=42866
Could you please help me and let me know what is wrong here and how could I fix it? Thanks!
If you use Db2 for LUW, then you shouldn't use SYSIBM schema in your queries on the system catalog. Use SYSCAT instead.
You don't have to use any functions to get what you want here. Use the following query instead:
SELECT TABSCHEMA, TABNAME, COLNAME, TYPENAME
FROM SYSCAT.COLUMNS
ORDER BY TABSCHEMA, TABNAME, COLNO;
As for your routine. There is a number of errors in the text.
1) if you want to assign multiple values with SET statement, you must use the corresponding number of parameter markers in the statement:
SET (?, ..., ?) = (SELECT COL1, ..., COLn FROM ...);
PREPARE S FROM L_STMT;
EXECUTE S INTO L_V1, ..., L_Vn;
2) RETURNS TABLE (...) and PIPE(...) must have the same number of columns
You could directly query the tables SYSCAT.COLUMNS and SYSCAT.TABLES. The following returns the table schema and name followed by column name and their type. Column info is sorted by the column order:
select t.tabschema, t.tabname, c.colname, c.typename, c.colno
from syscat.columns c, syscat.tables t
where t.type='T' and t.tabname=c.tabname and t.tabschema=c.tabschema
order by 1,2,c.colno
BTW: Db2 has a tool db2look to export schema information.

how to map column if exists otherwise empty

I'm trying to map a property to a Formula to select value if the column if exists otherwise default value
I tried the following
mapper.Map(x => x.GroupId).Formula("(select case when exists (select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL WHERE SYS_COLS_TBL.TABLE_NAME ='Azure' AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId') then this_.GroupId else '' end)");
I get an error
SqlException: Invalid column name 'GroupId'.
This SQL statement will return all tables, which do have name 'Azure'
select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL
WHERE SYS_COLS_TBL.TABLE_NAME ='Azure'
AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId'
but, there could be e.g. two such tables .. but in different schemas. And if that happens, we can be querying dbo.Azure .. while SomeOtherSchema.Azure is having column GroupId. This will fix it:
select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL
WHERE SYS_COLS_TBL.TABLE_NAME ='Azure'
AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId'
AND SYS_COLS_TBL.TABLE_SCHEMA = 'dbo'
Also, to support more complex querying (JOIN associations) remove this_.:
instead of:
then this_.GroupId else '' end)
use:
then GroupId else '' end)
NHibernate will provide proper alias based on context
The SQL statement requires that all references to the tables and columns do exist. Therefore you're getting Invalid column name 'GroupId' error.
The usual way to do something like that would be to use dynamic sql (sp_executesql #sql):
DECLARE #sql NVARCHAR(MAX) = '
SELECT '+
(CASE WHEN EXISTS (SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo' AND --assuming the schema is dbo
TABLE_NAME = 'Azure' AND
COLUMN_NAME = 'GroupId'
)
then 'GroupId'
else 'NULL as GroupId'
end) + '
FROM Azure';
exec sp_executesql #sql
But this would not work because you are already in the context of SQL statement and it is not possible to inject the dynamic sql there.
To solve the problem there are a few solutions:
Correct solution: create the missing columns in the database.
Painful solution: map the object to a stored procedures which will execute a dynamic SQL similar to the above.
Insanely painful solution: Map your possible missing columns as normal. Before building the factory - introspect your model and either remove mappings for the columns missing or change their mapping to formulas. This would be similar to Configuration.ValidateSchema method of NHibernate, but instead of throwing errors - you'd need to remove these columns from the mapping.

Getting column name in Microsoft SQL Server (c#)

I'm working in Visual Studios 2017 and I need to get the column names of a datatable named "Question" , from a database named "qst". Is there any way, or command that can get me the column name and then insert it in richTextBox1?
As variant you can use the following query to get all column names for a table
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='YourTableName'
ORDER BY ORDINAL_POSITION
If it's necessary all table names you can get from INFORMATION_SCHEMA.TABLES
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'

How to assign a column to a dynamic variable

One column in one table of my database say (Table A and Column A) can be either of Numeric type or VARCHAR type. Datatype is decided dynamically and then table gets created.
I need to create a dynamic variable (#Dynamic) which should check the datatype of this column and assign a different column (column B or column C) to it accordingly i.e.
If column A is NVARCHAR, assign column B to #Dynamic
If column A is NUMERIC, assign column C to #Dynamic
I've to do this in both SQL Server and Oracle.
Any help to write a function for this would be greatly appreciated.
In sql server you can check column data type
SELECT DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'Table A'
AND COLUMN_NAME = 'Column A'
In oracle
SELECT Type
FROM user_tab_columns
WHERE table_name = 'Table A'
AND column_name = 'Column A';
Sql_variant is a dynamic type in SQL Server. The eqivalent in oracle would be anydata type.
But if you are using dynamic SQL why don't you store the data in nvarchar as it is big enough for the convertet numeric values as well and you can use it directly for your dynamic SQL statement?
Actually this was a generic question and did not need any sample data to answer.
The approach I am following is:
I wrote a function
CREATE FUNCTION [dbo].[GET_DATA_TYPE] (#input VARCHAR)
RETURNS VARCHAR(255) AS
BEGIN
DECLARE #l_data_type VARCHAR(255)
SELECT #l_data_type=DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = #input AND
COLUMN_NAME = 'AssetID'
RETURN #l_data_type
END
I would call this function in my stored procedures as
SELECT #dataType = dbo.GET_DATA_TYPE(#input);
I declared another variable i.e. #FinalType
IF #dataType == 'numeric'
THEN #FinalType = columnC
IF #dataType == 'nvarchar'
THEN #FinalType = columnD
Then I'll use this #FinalType variable in all my dynamic sqls.
Any other efficient way to do this.

How can i check in MS SQL Server 2005 if a column is of a specific type

I want to change the type of a column in MS SQL Server 2005, but before i change the type of that column i want to check if that column is of the type i want to change. How can i do that in SQL?
Thanxs,
Bas Hendriks.
Based on the anwser i wrote the following query that did the trick:
IF NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'e_application'
AND COLUMN_NAME = 'txt_locked_by'
AND DATA_TYPE = 'nvarchar'
AND CHARACTER_MAXIMUM_LENGTH = 15 )
BEGIN
ALTER TABLE.....
END
You can query the INFORMATION_SCHEMA tables.
E.g.
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable'
you can use sp_help TableName , it also retrieve's the column's data types and other properties