This could be a strange question.
I have a table with 100+ columns. I would like to SELECT * all columns and get the resulting query with columns ordered alphabetically.
Is it possible in T-SQL?
Thanks
You could build a dynamic SQL statement using the information available in the system catalog view.
The sample code below shows how:
DECLARE #sql AS NVARCHAR(MAX)
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #tbl NVARCHAR(MAX) = N'your_table' -- this is your source table
SELECT #cols= ISNULL(#cols + ',','') + QUOTENAME(c.name)
FROM sys.tables t
join sys.columns c ON c.object_id = t.object_id
WHERE t.name = #tbl
ORDER BY c.name
SET #sql = N'SELECT ' + #cols + ' FROM ' + #tbl
EXEC sp_executesql #sql
DynamicSQL (SQL Server) example:
declare #TABLE varchar(200) set #TABLE='persons'
declare #SQL nvarchar(max)
set #SQL='select '
select #SQL= #SQL + column_name + ','
from information_schema.columns where table_name=#TABLE order by column_name
select #SQL = left(#SQL,len(#SQL)-1) + ' from ' + #TABLE -- trims the trailing comma
--select #SQL -- If you want to see the query
exec sp_executesql #SQL
DECLARE #Table NVARCHAR(MAX)='T'--pass your table name
DECLARE #SQL NVARCHAR(MAX)='SELECT '
SELECT #SQL=#SQL+',' +NAME FROM
(
SELECT TOP 100 QUOTENAME(NAME) AS NAME
FROM sys.columns
WHERE object_id =
(
SELECT OBJECT_ID FROM sys.tables
WHERE NAME =#Table
)
ORDER BY NAME
) AS SS
SELECT #SQL=STUFF(#SQL,8,1,'')+' FROM '+#Table
EXEC sp_executesql #sql
Related
Im new to Stack overflow and SQL and I'm trying to replicate a function in Microsoft Power Query to use in SQL instead.
I know how to Unpivot and keep 1 Column in SQL and then had to reference all the other columns by name to make the unpivot.
Now I need to Keep 3 ID columns and Unpivot the rest of the columns
(This table has 355 columns right now and will change)
Can anyone help me with this?
This is the furthest I got (Thanks to RAV DBLearning on Youtube), but I cant seem to find a way to Convert the columns types to 1 type.
DECLARE
#SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(1000) = ''
SELECT
#COLUMNLIST = #COLUMNLIST + QUOTENAME(NAME) + ','
FROM
sys.columns
WHERE
OBJECT_ID = OBJECT_ID('xp.XPROPERTYVALUES') AND
--COLUMN_ID NOT IN(1,2,3)
COLUMN_ID IN(452,453,454)
SELECT
#COLUMNLIST = LEFT(#COLUMNLIST,LEN(#COLUMNLIST)-1)
SET
#SQLSTRING =
'
SELECT
upv.id,
upv.item_id,
upv.itemtype_id,
upv.X_Category,
upv.X_Values
FROM
xp.XPROPERTYVALUES
UNPIVOT
(
X_Values FOR X_Category
IN
(' + #COLUMNLIST + ')
) AS upv
'
PRINT
(#SQLSTRING)
EXECUTE
sp_executesql #SQLSTRING
It just needs a source query.
And you can re-use the calculated column list for that.
DECLARE #SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(MAX);
DECLARE #TABLENAME VARCHAR(30) = 'xp.XPROPERTYVALUES';
SELECT #COLUMNLIST = CONCAT(#COLUMNLIST + ', ', QUOTENAME(NAME))
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(#TABLENAME)
AND LOWER(NAME) NOT LIKE '%id';
SET #SQLSTRING = N'SELECT upv.id
, upv.item_id, upv.itemtype_id
, upv.X_Category, upv.X_Values
FROM
(
SELECT id, item_id, itemtype_id,
'+ #COLUMNLIST + N'
FROM '+ #TABLENAME +N'
) src
UNPIVOT
(
X_Values FOR X_Category IN (' + #COLUMNLIST + N')
) upv';
-- SELECT #SQLSTRING;
EXECUTE sp_executesql #SQLSTRING;
db<>fiddle here
I want to select phone numbers from all tables in my databese and names of these tables too. I write a query that shows me all phone_numbers but I dont't know how to select table name to each phone number. This is my query:
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'SELECT phone_number FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES where table_name in (select table_name
from information_schema.columns
where column_name = 'phone_number'
)
You can simply add the table name as a constant to the SELECT clause. But, I presume you're going to want to run this query, which means you have a few more things to change:
You're probably going to want sp_executesql, which requires a Unicode variable. So, you need to DECLARE #SQL NVARCHAR(MAX).
Do you want one result set or multiple result sets? I'm guessing you want all the results in one result set, which means you're going to want to use UNION ALL between the parts of the query.
So, try something like this:
DECLARE #sql NVARCHAR(MAX)
SET #sql = N'SELECT '''' AS table_name, '''' AS phone_number FROM [dbo].[SomeTable] WHERE 1 = 0'
DECLARE #table_name SYSNAME
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT table_name
FROM INFORMATION_SCHEMA.columns
WHERE column_name = 'phone_number'
OPEN cur
FETCH NEXT FROM cur INTO #table_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = #sql + N' UNION ALL SELECT ''' + #table_name + N''', phone_number FROM [' + #table_name + N']'
FETCH NEXT FROM cur INTO #table_name
END
CLOSE cur
DEALLOCATE cur
EXEC sp_executesql #sql
When I used [dbo].[SomeTable], just use some table that you know exists. You would also need to modify the query if you want fully-qualified table names, but the above should get you started.
Another solution without CURSOR. You could combine each query with UNION like this.
--SELECT DISTINCT phone_number FROM dbo.Course c
DECLARE #sql nvarchar(max) = ''
SELECT #sql = #sql + N' SELECT DISTINCT phone_number, '''+ s.name + '.' + t.name + ''' AS TableName
FROM '+ s.name + '.' + t.name + Char(13) + ' UNION' + char(13)
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.columns c ON c.object_id = t.object_id
WHERE c.name ='phone_number'
IF(#sql != '')
BEGIN
SET #sql = LEFT(#sql,len(#sql) - 6) -- remove last UNION
PRINT #sql
-- execute sql
EXEC sp_executesql #sql
END
I also add column TableName: Table of phone_number
If you want TableName if the first column then change it
SELECT #sql = #sql + N' SELECT DISTINCT '''+ s.name + '.' + t.name + ''' AS TableName, phone_number
FROM '+ s.name + '.' + t.name + Char(13) + ' UNION' + char(13)
I have a table named a. Some cells containing a string 'Empty' in many columns. I want to find this columns. Can you help me?.
Try this dynamic query, it will check all the columns with character data and list the columns which has the word 'Empty'.
DECLARE #SearchText VARCHAR(50) = 'Empty'
DECLARE #sql NVARCHAR(MAX) = 'SELECT '
SELECT #sql = #sql + 'MAX(CASE WHEN ' + c.COLUMN_NAME + ' LIKE ''%'+ #SearchText +'%'' THEN ''' + c.COLUMN_NAME +''' ELSE '''' END) + '','' + '
FROM INFORMATION_SCHEMA.COLUMNS c WHERE c.TABLE_SCHEMA = 'dbo' and c.TABLE_NAME = 'a'
AND c.DATA_TYPE IN ('varchar','char','nvarchar','nchar','sysname')
SET #sql = #sql + ''''' FROM dbo.a'
EXEC sys.sp_executesql #sql
Hope this helps
Use the LIKE operator:
SELECT a.*
FROM a
WHERE a.col1 LIKE '%Empty%' OR a.col2 LIKE '%Empty%' OR ...
In sql server you can get object id of table then using that object id you can fetch columns. In that case it will be as below:
Step 1: First get Object Id of table
select * from sys.tables order by name
Step 2: Now get columns of your table and search in it:
select * from a where 'Empty' in (select name from sys.columns where object_id =1977058079)
Note: object_id is what you get fetch in first step for you relevant table
You can do it using unpivot with an help of dynamic query , here i have done below an working sample for you , there might be some modification you might have to do to put the below psedo code with your working .
Sample table structure been used :
create table ColTest
(
name1 varchar(10),
name2 varchar(10),
name3 varchar(10),
name4 varchar(10)
)
insert into ColTest values ('sdas','asdasda','ewrewr','erefds')
insert into ColTest values ('sdas','asdasda','EMPTY','erefds')
insert into ColTest values ('EMPTY','asdasda','ewrewr','erefds')
DECLARE #table_name SYSNAME
SELECT #table_name = 'ColTest'
DECLARE #tmpTable SYSNAME
SELECT #tmpTable = 'ColTest2'
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = '
SELECT * into
' + #tmpTable + '
FROM ' + #table_name + '
UNPIVOT (
cell_value FOR column_name IN (
' + STUFF((
SELECT ', [' + c.name + ']'
FROM sys.columns c WITH(NOLOCK)
LEFT JOIN (
SELECT i.[object_id], i.column_id
FROM sys.index_columns i WITH(NOLOCK)
WHERE i.index_id = 1
) i ON c.[object_id] = i.[object_id] AND c.column_id = i.column_id
WHERE c.[object_id] = OBJECT_ID(#table_name)
AND i.[object_id] IS NULL
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + '
)
) unpiv'
PRINT #SQL
EXEC sys.sp_executesql #SQL
select * from ColTest2 where cell_value = 'EMPTY'
I'd suggest dynamic SQL
--First you set the variable #TableName to your actual table's name.
DECLARE #TableName VARCHAR(100)='a';
--The following statement will create a list of all columns with a data type containing the word "char" (others should not hold the value Empty)
DECLARE #ColList VARCHAR(MAX)=
STUFF(
(
SELECT ' OR ' + COLUMN_NAME + ' LIKE ''%empty%'''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=#TableName AND DATA_TYPE LIKE '%char%'
FOR XML PATH('')
),1,4,'');
--This statement builds a command
DECLARE #cmd VARCHAR(MAX)=
(
SELECT 'SELECT * FROM [' + #TableName + '] WHERE ' + #ColList
);
--Here you can see the command
PRINT #cmd;
--And here it is executed
EXEC(#cmd);
I have been working to make a dynamic pivot in SQL Server that a user could call in a stored procedure and pass specified parameters ie:
exec piv(schema, table, agg_type, aggCol, newCol)
I am struggling to finish out the schema and table parameters.
Here is what I have so far:
BEGIN
DECLARE #Piv AS NVARCHAR(max) --final pivot. print this to see the exec statement
DECLARE #NewColumns AS NVARCHAR(max) -- extract data and format to make new columns
DECLARE #COLUMNS AS NVARCHAR(MAX) -- list of all columns to be used for CTE below
DECLARE #PivColumns AS NVARCHAR(MAX) --list of all columns except the 2 columns involved in pivot
--declaring parameters here for now
declare #aggCol nvarchar(max)
declare #newCol nvarchar(max)
declare #table nvarchar(max)
declare #schm nvarchar(max)
--To be used for parameters in the SP
set #schm = 'dbo'
set #table = 'Report'
set #aggCol = 'Flag'
set #newCol = 'Category'
-- extracts data and formats for new columns... here is where I'm stuck.
-- I have tried every way I can find to pass the variables in this statement and no luck
SELECT #NewColumns = COALESCE(#NewColumns + ',','') + QUOTENAME(CATEGORY) + char(13)
FROM
(
SELECT DISTINCT Category --needs to be dynamic ie: #newCol
FROM
dbo.Report --needs to be dynamic ie: #table
) AS B
-- list of all columns to be used for CTE below
SELECT #Columns = COALESCE(#Columns + ',','') + QUOTENAME(COLUMN_NAME) + char(13)
FROM
(
SELECT DISTINCT COLUMN_NAME
FROM
(
SELECT
SCHEMA_NAME(T.SCHEMA_ID) AS 'SCHEMA_NAME' -- GET THIS WORKING TO GET A SPECIFIC TABLE
,T.NAME AS 'TABLE_NAME'
,C.NAME AS 'COLUMN_NAME'
FROM SYS.COLUMNS C
INNER JOIN SYS.TABLES T ON C.OBJECT_ID = T.OBJECT_ID
WHERE T.NAME = #table) AS A
) AS B
ORDER BY B.COLUMN_NAME
--list of all columns except the 2 columns involved in pivot
SELECT #PivColumns =
COALESCE(#PivColumns + ',','') + QUOTENAME(COLUMN_NAME) + char(13)
FROM
(
SELECT DISTINCT COLUMN_NAME
FROM
(
SELECT
SCHEMA_NAME(T.SCHEMA_ID) AS 'SCHEMA_NAME' -- GET THIS WORKING TO GET A SPECIFIC TABLE
,T.NAME AS 'TABLE_NAME'
,C.NAME AS 'COLUMN_NAME'
FROM SYS.COLUMNS C
INNER JOIN SYS.TABLES T ON C.OBJECT_ID = T.OBJECT_ID
WHERE T.NAME = #table
and (C.name not like #aggCol or C.name not like #newCol)
) AS A
) AS B
ORDER BY B.COLUMN_NAME
--Removes columns that are used on the pivot
SET #PivColumns = REPLACE(REPLACE(#PivColumns,char(13)+',['+#aggcol+']',''),char(13)+',['+#newcol+']','')
--final statement to print/exec
SET #Piv ='
WITH T1 AS
(
SELECT
'+#COLUMNS+'
FROM
'+#table+'
)
SELECT
'+#PivColumns+'
,'+#NewColumns+'
FROM T1
PIVOT
(MAX(FLAG) FOR CATEGORY IN ('+#NewColumns+'))AS PIV'
print(#Piv)
END
Feel free to add suggestions or edit in any way ie: tempTable, cte, etc...
I built this in another window that gets me what I need but I do not think I can use it in the first statement:
BEGIN
DECLARE #NewColumns AS NVARCHAR(max)
declare #newCol nvarchar(max)
declare #table nvarchar(max)
set #newCol = 'Category'
set #table = '[dbo].[REPORT]'
Select #NewColumns =
'
DECLARE #NewColumns AS NVARCHAR(max)
declare #table nvarchar(max)
SELECT #NewColumns = COALESCE(#NewColumns + '','','''') + QUOTENAME(CATEGORY) + char(13)
FROM
(
SELECT DISTINCT '+#newCol+'
FROM
'+#table+'
) AS B
print(#NewColumns)
'
exec(#NewColumns)
end
Try this
DECLARE #SQL VARCHAR(MAX)
DECLARE #List VARCHAR(MAX)
DECLARE #SQLList nVARCHAR(MAX)
SET #SQLList=N'select #List=stuff((SELECT DISTINCT '',''+AccountType FROM '+#table+'. FOR XML PATH('''')),1,1,'''')'
exec sp_executesql #SQLList ,N'#List VARCHAR(MAX) out', #List out
select #List
SET #SQL=
'
SELECT * FROM (SELECT '+#newCol +','+#aggCol+'
FROM '+#table+') AS SourceTable
PIVOT
(
'+#agg_type+'('+#aggCol+')
FOR '+#newCol +'IN ('+#List+')
) AS PivotTable;'
exec(#SQL)
Does anybody know of a proc or script which will generate any row into an insert statement into the same table?
Basically, I'd like to call something like
exec RowToInsertStatement 'dbo.user', 45;
And the following code would be output
insert into dbo.MyTable( FirstName, LastName, Position)
values( 'John', 'MacIntyre', 'Software Consultant');
I realize I could
insert into dbo.MyTable
select * from dbo.MyTable where id=45;
But this obviously won't work, because the ID column will complain (I hope it complains) and there's no way to just override that one column without listing all columns, and in some tables there could be hundreds.
So, does anybody know of a proc that will write this simple insert for me?
EDIT 3:04: The purpose of this is so I can make a copy of the row, so after the INSERT is generated, I can modify it into something like
insert into dbo.MyTable( FirstName, LastName, Position)
values( 'Dave', 'Smith', 'Software Consultant');
.. no obviously this contrived example is so simple it doesn't make sense, but if you have a table with 60 columns, and all you need is to change 3 or 4 values, then it starts to be a hassle.
Does that make sense?
Update
I believe the following dynamic query is what you want:
declare #tableName varchar(100), #id int, #columns varchar(max), #pk varchar(20)
set #tableName = 'MyTable'
set #pk = 'id'
set #id = 45
set #columns = stuff((select ',['+c.name+']' [text()] from sys.tables t
join sys.columns c on t.object_id = c.object_id
where t.name = #tableName and c.name <> #pk for xml path('')),1,1,'')
print 'insert into [' + #tableName + '] (' + #columns + ')
select ' + #columns + '
from [' + #tableName + ']
where ' + #pk + ' = ' + cast(#id as varchar)
Update 2
The actual thing that you wanted:
declare #tableName varchar(100), #id int, #columns nvarchar(max), #pk nvarchar(20), #columnValues nvarchar(max)
set #tableName = 'MyTable'
set #pk = 'id'
set #id = 45
set #columns = stuff((select ',['+c.name+']' [text()] from sys.tables t
join sys.columns c on t.object_id = c.object_id
where t.name = #tableName and c.name <> #pk for xml path('')),1,1,'')
set #columnValues = 'set #actualColumnValues = (select' +
stuff((select ','','''''' + cast(['+c.name+'] as varchar(max)) + '''''''' [text()]' [text()]
from sys.tables t
join sys.columns c on t.object_id = c.object_id
where t.name = #tableName and c.name <> #pk for xml path('')),1,1,'')
+ 'from [' + #tableName + ']
where ' + #pk + ' = ' + cast(#id as varchar)
+ 'for xml path(''''))'
--select #columnValues
declare #actualColumnValues nvarchar(max), #columnValuesParams nvarchar(500)
SET #columnValuesParams = N'#actualColumnValues nvarchar(max) OUTPUT';
EXECUTE sp_executesql #columnValues, #columnValuesParams, #actualColumnValues OUTPUT;
--SELECT stuff(#actualColumnValues, 1,1, '')
declare #statement nvarchar(max)
set #statement =
'insert into [' + #tableName + '] (' + #columns + ')
select ' + stuff(#actualColumnValues,1,1,'')
print #statement
What it does is this:
It generates the insert statement and then it queries the actual data from the table and generates the select statement with that data. May not work correctly for some really complex datatypes but for varchars, datetimes and ints should work like a charm.
This stored proc works great for me:
http://vyaskn.tripod.com/code.htm#inserts
Did you know that in Enterprise Manager and SQL Server Management Studio that you can, from the object browser, drag the list of columns into the text window and it will drop the names of all the columns into the text, separated by commas?