Dynamically insert column names into function - sql

I try to insert column names into my query to obtain the max-length of the underlying data-input, like:
DECLARE #cols AS varchar(MAX)
,#query AS nvarchar(MAX)
SELECT #cols = (
select STRING_AGG(COLUMN_NAME, ',')
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='mytbl'
and TABLE_SCHEMA = 'dbo'
and DATA_TYPE = 'varchar'
)
set #query = 'select top(1) max(datalength(' + #cols + ')) FROM dbo.mytbl'
exec sp_executesql #query;
.. which prompts the following error:
The datalength function requires 1 argument(s).
I donĀ“t know how to cast the string so that the #cols are recognized by the encasing max(datalength()) function(s).
Any ideas how to circumvent this error? I am out of ideas.
UPDATE:
The intended output should look something like that:
select max(datalength(col1))
,max(datalength(col2))
,max(datalength(col3))
,max(datalength(col4))
...
from dbo.mytable
which works and gives me the max-char of any input per column, like:

you need to apply the MAX() and DATALENGTH() on the column before concatenation
Change the #cols to
SELECT #cols = (
select STRING_AGG('MAX(DATALENGTH(' + COLUMN_NAME + '))', ',')
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='mytbl'
and TABLE_SCHEMA = 'dbo'
and DATA_TYPE = 'varchar'
)
and the final #query is just a simple select
set #query = 'select ' + #cols + ' FROM dbo.mytbl'
You should print out the query for inspection, before execute it
print #query

Related

query by partial column name

I have a
Checklist table and
there is 27 columns named "check1", "check2"..."check27".I would like to get all this values doing a query something like:
SELECT "check*" FROM Checklist;
Is this possible?
Which database? postgres, sqlite, mysql?
If select * is not an option, the most flexible approach is creating a dynamic query. You will first need to get the column names and then build your query:
DECLARE #tableName as varchar(100);
SET #tableName = 'Checklist';
DECLARE #columnList varchar(300);
SELECT #columnList = COALESCE(#columnList + ', ', '') + sc.name
FROM sysobjects so
INNER JOIN syscolumns sc ON so.id = sc.id
WHERE so.name = #tableName
AND sc.name LIKE 'check%'
DECLARE #query as varchar(4000);
SET #query = 'SELECT ' + #columnList + ' FROM ' + #tableName;
EXEC(#query);
The ending #query should contain SELECT check1, check2, check... FROM Checklist.
In Sql Server, this is terrible but you could do it... Building dynamic SQL
check% being your check* in the Select #columns query
DECLARE #columns NVARCHAR(max);
SELECT #columns = STUFF((
SELECT ',' + column_name
FROM INFORMATION_SCHEMA.columns
WHERE table_name = 'Checklist'
AND column_name LIKE 'check%'
FOR XML path('')
), 1, 1, '')
DECLARE #statement nvarchar(max) = 'SELECT ' + #columns + ' FROM Checklist'
EXECUTE sp_executesql #statement
Troll ass answer...
SELECT check1,check2,check3,check4,check5,check6,check7,check8,check9,check10,check11,check12,check13,check14,check15,check16,check17,check18,check19,check20,check21,check22,check23,check24,check25,check26,check27 FROM Checklist;

T-SQL: Select data from all tables reverted by INFORMATION_SCHEMA.TABLES

I need to extract data from all tables that were reverted by following query:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%'
I've tried to execute following query, but without success:
SELECT *
FROM
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%')
WHERE STATUS = 'XXX'
Looking forward to your assistance.
You may try to generate a dynamic SQL statement and execute it:
-- Declarations
DECLARE #stm nvarchar(max)
SET #stm = N''
-- Dynamic SQL
SELECT #stm = (
SELECT CONCAT(
N'SELECT * FROM ',
QUOTENAME(TABLE_NAME),
N' WHERE [STATUS] = ''XXX''; '
)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%'
FOR XML PATH('')
)
-- Execution
PRINT #stm
EXEC sp_executesql #stm
Try this query using dynamic SQL:
declare #sql varchar(max) = '';
select #sql = #sql + 'select * from ' + TABLE_NAME + ' where [status] = ''XXX''; '
from INFORMATION_SCHEMA.TABLES
where TABLE_NAME like 'ERP_%';
exec(#sql);

SQL - Subquery (Column names)

I need a select query thats returns the value of some columns.
The column that I want starts with 'U_S'.
Select * from em
I need to transform the query above. The '*' needs to be the result (but with commas) of:
select COLUMN_NAME from information_schema.columns
where table_name='em' and column_name like 'u_s%'
There are countless examples like this, but I understand that sometimes we all need a little kick-start.
Select Stuff((Select ',' +quotename(Column_Name)
From information_schema.columns
Where table_name='em' and column_name like 'u_s%'
For XML Path ('')),1,1,'')
you can use code like below:
declare #col varchar(500)
select #col=Stuff((Select ',' +quotename(Column_Name)
From information_schema.columns
Where table_name='em' and column_name like 'u_s%'
For XML Path ('')),1,1,'')
exec('select '+#col
+' from em')
select CAST(
(select COLUMN_NAME + ','
from information_schema.columns
where table_name='em' and column_name like 'u_s%'
for xml path('')
) as nvarchar(max)
)
you will have to delete last comma...
You can also select the column names directly into a variable, which can then be used for a Dynamic SQL.
declare #Cols varchar(max) = null;
select #Cols = concat(#Cols +', ',quotename(COLUMN_NAME))
from information_schema.columns
where table_name='em' and column_name like 'u_s%'
order by column_name;
--select #Cols as Cols;
declare #SQL varchar(max);
set #SQL = 'select '+ #Cols +' from em';
exec(#SQL);
#Cols is null at first, and null+',' gives null.
So the result won't start with a comma.
The quotename function is just added as a safety measure.
Just in case the columnnames sometimes have spaces in the name.

How to display the table name in a union query

The following script is working well:
DECLARE #SelectClause VARCHAR(100) = 'SELECT id_contato'
,#Query VARCHAR(8000) = ''
SELECT #Query = #Query + #SelectClause + ' FROM ' + TABLE_NAME + ' UNION ALL '
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE '%zumbi' or TABLE_NAME like '%engajado%')
SELECT #Query = LEFT(#Query, LEN(#Query) - LEN(' UNION ALL '))
EXEC (#Query)
But I need a second column with the table name to identify where the information came from.
How can I do that?
You're utilizing the table_name field already in your query, just need to add it to your SELECT and quote it properly so it comes back as string literal:
DECLARE #SelectClause VARCHAR(100) = 'SELECT id_contato'
,#Query VARCHAR(8000) = ''
SELECT #Query = #Query + #SelectClause + ','''+Table_Name+''' AS Table_Name FROM ' + TABLE_NAME + ' UNION ALL '
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE '%zumbi' or TABLE_NAME like '%engajado%')
SELECT #Query = LEFT(#Query, LEN(#Query) - LEN(' UNION ALL '))
EXEC (#Query)
Updated quotes, works for me in SQL Server.

Query Result(NULL value/Datetime format)

I have this query that I use for put all the rows in one column, is dynamic because I need to do this with at least 8 tables:
DECLARE #tblName VARCHAR(20) = 'Location'
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX)
SELECT #columns = COALESCE(#columns, '') + '+[' + COLUMN_NAME + '],+'''''','''''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tblName and TABLE_SCHEMA='LES'
select #columns
SET #sql = 'SELECT CONCAT(''''''''' + STUFF(#columns, 103,9, '') + '+'''''') FROM ' + #tblName
select #sql
--------------------------------------------------------------------------
R1: SELECT CONCAT(''''+[Location],+''','''+[Location Type],+''','''+[Region],+''','''+[World Region],+''','''+[Refresh Date]+''') FROM Location
If I execute the query (without the datetime column (Refresh Date) that contains NULL values) the result will be
'0020319389','CMF','AJ','AJ'
'0031209263','CMF','AJ','AJ'
'01BM','DCL','EU','EU'
'01CR','DCL','EU','EU'
My problem here is that when I execute the query with the Refresh_date column, I get this error:
Conversion failed when converting date and/or time from character string.
Can anybody help me please?
Thanks
Your problem is that you're mixing old school concatenation, + with the 2012/2014 CONCAT function and data precedence rules are in effect.
This bit of code is using old school syntax
SELECT #columns = COALESCE(#columns, '') + '+[' + COLUMN_NAME + '],+'''''','''''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tblName and TABLE_SCHEMA='LES'
Instead, make it use a CONCAT, then your data type precedence will convert your date times to a string as well as handle NULLs.