SQL Column Name wildcard - sql

I have a table with 30+ fields and I want to quickly narrow my selection down to all fields where column name start with 'Flag'.
select * Like Flag% from Table1

You will want to build a dynamic query as explained here: https://stackoverflow.com/a/4797728/9553919
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Foods'
AND table_schema = 'YourDB'
AND column_name LIKE 'Vegetable%'

This SQL Statement should be useful. You may be able to simplify it but it does work.
Edit2: I just now saw your pervasive-sql tag. Unfortunately I've never worked with that and don't know if the syntax is compatible with MS SQL Server. I'll let my answer here in case it helps others, but wanted to share that I tested this using SQL Server.
Edit: SCHEMA_NAME function isn't necessary. You can replace SCHEMA_NAME(schema_id) with the name of your schema in single quotes if you want, but either will work.
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM
sys.tables AS t
INNER JOIN
sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE
t.name = 'Table1' AND
c.name Like 'Flag%'
ORDER BY
c.name
or
SELECT t.name AS table_name,
'MySchema' AS schema_name,
c.name AS column_name
FROM
sys.tables AS t
INNER JOIN
sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE
t.name = 'Table1' AND
c.name Like 'Flag%'
ORDER BY
c.name

To do this, you will need to query the system tables for the columns associated to the table and filter them to what you want. From there, place them into a variable table and create a CSV of columns. From there, you can dynamically construct your query as needed. The below example should help you get started.
DECLARE #tableName VARCHAR(100) = 'dbo.SomeTable'
DECLARE #columnNames TABLE
(
Id INT IDENTITY PRIMARY KEY,
ColumnName VARCHAR(100)
)
--Grabs all of the columns into a variable table
INSERT INTO #columnNames (ColumnName)
SELECT
[name]
FROM sys.columns
WHERE
[object_id] = OBJECT_ID(#tableName)
AND
[name] LIKE '%Flag'
DECLARE #columns VARCHAR(1000)
--Creates a CSV of columns
SET #columns =
STUFF(
(
SELECT
',' + ColumnName
FROM #columnNames
FOR XML PATH(''))
,1,1,'')
DECLARE #selectStatement NVARCHAR(4000) = CONCAT('SELECT ', #columns, ' FROM ', #tableName)
PRINT #selectStatement
EXEC #selectStatement

Related

Inserting into production table from the latest archive table

I have a project where I need to insert into a production table the data that is in an archive table. The problem is that I have multiple archive tables for a specific table, all with a timestamp at the end of the table name. My idea was to find the latest archive table by doing this:
select top (1) table_name from INFORMATION_SCHEMA.tables where TABLE_CATALOG = 'databasename' and table_name like 'archive_User_%' order by table_name desc
This will give me the name of the last archive table for "User".
Question is, how to I write my insert into query to use this as the name of the table I want to insert into from?
Thanks!!!
how to I write my insert into query to use this as the name of the table I want to insert into from?
Dynamic SQL. EG:
declare #tn sysname
declare #schema sysname
select top (1) #tn = name , #schema = schema_name(schema_id)
from sys.tables
where name like 'archive_User_%'
order by name desc
declare #sql nvarchar(max) = concat( '
insert into sometable (a,b,c,d)
select a,b,c,d
from ',quotename(#schema),'.',quotename(#tn),';
')
--print #sql
exec sp_executesql #sql
Declare #QueryText nVarChar(max)
Select #QueryText = Concat('Insert Into ', QuoteName(s.name), '.', QuoteName(t.name), ' (',
STRING_AGG(c.name,', '), ')', Char(10), 'Select ', STRING_AGG(c.name,', '),
Char(10),'From ', QuoteName(t1.schemaName), '.', QuoteName(t1.tableName))
From sys.tables as t Inner Join sys.schemas as s On (t.schema_id=s.schema_id)
Inner Join sys.columns as c On (t.object_id=c.object_id)
,(Select Max(name) As tableName, schema_name(schema_id) as
schemaName From sys.tables Where name Like 'archive_User_%'
And schema_name(schema_id)='SchemaName' Group by
schema_name(schema_id)) As t1
Where t.name = 'TableName'
And s.name = 'SchemaName'
-- And c.name Not In ('ColumnName1','ColumnName2')
Group by s.name, t.name, t1.tableName, t1.schemaName
Execute sp_executesql #QueryText

Retrieving which database(s) and tables contains a spesific column name within a multiple database soloution

I wish do retrieve the database which contains table x, based on a column name I enter through e.g. My WHERE statement.
As of now, I run two seperate SELECT queries. Firstly, I search for which tables in the soloution contains a spesific column.
Second, I have to manually search for all the resulting databases in the subquery.
I wish to have this dynamic, so that when entering the column name, both database and table are returned. Now, I get "NULL" the Database column.
I've managed to get the current db using only db_name, but that is not what I intend to do..
db_name(db_id(table1.name)) AS "Database" , table1.name AS 'Table', column1.name AS 'Column'
FROM sys.columns column1
JOIN sys.tables table1 ON column1.object_id = table1.object_id
WHERE column1.name LIKE 'columnname'
ORDER BY "Table", "Column"
(SELECT "db" FROM sys.databases WHERE CASE WHEN state_desc = 'ONLINE' THEN
OBJECT_ID(QUOTENAME("db") + '.[dbo].' + '[database1]', 'U')
END IS NOT NULL)
The code above is working wiithout errors. However, I do not manage to pull the Database name, and I can not understand how I could solve this.
I've used several earlier posts as reference to build up this code, as I'm a rookie to SQL.. :-)
Thanks in advance for any assitance.
Br.
This gives a bit more information than you requested, but it's a code that I had to create a data dictionary of my databases. You just need to change the value for the first variable to make it work.
--Change this value
DECLARE #ColumnName sysname = 'YourColumnName';
IF OBJECT_ID( 'tempdb..#DataDictionary') IS NOT NULL
DROP TABLE #DataDictionary;
CREATE TABLE #DataDictionary(
TABLE_CATALOG sysname,
TABLE_SCHEMA sysname,
TABLE_NAME sysname,
ORDINAL_POSITION int,
COLUMN_NAME sysname,
DATA_TYPE sysname,
IS_NULLABLE varchar(8)
);
DECLARE #SQL NVARCHAR(MAX);
DECLARE dbs CURSOR LOCAL FAST_FORWARD
FOR
SELECT REPLACE( 'USE <<database_name>>;
INSERT INTO #DataDictionary
SELECT DB_NAME() AS TABLE_CATALOG,
s.name AS TABLE_SCHEMA,
t.name AS TABLE_NAME,
COLUMNPROPERTY(c.object_id, c.name, ''ordinal'') AS ORDINAL_POSITION,
c.name AS COLUMN_NAME,
CASE WHEN ty.name IN (''char'', ''varchar'', ''varbinary'', ''binary'') THEN CONCAT( ty.name, ''('', ISNULL( CAST(NULLIF(c.max_length, -1) AS varchar(4)), ''MAX''), '')'')
WHEN ty.name IN (''nchar'', ''nvarchar'') THEN CONCAT( ty.name, ''('', ISNULL( CAST(NULLIF(c.max_length, -1)/2 AS varchar(4)), ''MAX''), '')'')
WHEN ty.name IN (''numeric'', ''decimal'') THEN CONCAT( ty.name, ''('', c.precision, '','', c.scale, '')'')
ELSE ty.name END AS DATA_TYPE,
IIF(c.is_nullable = 1, ''NULL'', ''NOT NULL'') AS IS_NULLABLE
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE t.object_id NOT IN( SELECT major_id FROM sys.extended_properties WHERE minor_id = 0 AND class = 1 AND name = N''microsoft_database_tools_support'')
AND c.name = #ColumnName;', '<<database_name>>', name)
FROM sys.databases
WHERE database_id > 4 --No system databases
AND HAS_DBACCESS( name) = 1
AND state_desc = 'ONLINE'
OPEN dbs;
FETCH NEXT FROM dbs INTO #SQL;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_executesql #SQL, N'#ColumnName sysname', #ColumnName;
FETCH NEXT FROM dbs INTO #SQL;
END;
CLOSE dbs;
DEALLOCATE dbs;
SELECT *
FROM #DataDictionary
ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;
To get all the columns, just remove the column name comparison in the dynamic code AND c.name = #ColumnName

Get row count for a list of tables

In SQL Server 2008, how can I get a row count for a list of tables?
I have a database where I would like to get the row count for all tables that begin with 'BB'
I've tried multiple variations of this:
CREATE TABLE #RowCounts(NumberOfRows BIGINT, TableName VARCHAR(128))
EXEC sp_MSforeachtable 'INSERT INTO #RowCounts
SELECT COUNT_BIG(*) AS NumberOfRows,
''?'' AS TableName FROM ?'
SELECT TableName, NumberOfRows
FROM #RowCounts
ORDER BY NumberOfRows DESC, TableName
DROP TABLE #RowCounts
Throwing in stuff like ''?'' AS TableName FROM ? WHERE ? LIKE 'BB%'
and ''?'' AS TableName FROM ? WHERE ''?'' LIKE 'BB%'
I'm sure that there has to be a way to do this. If you can get the rowcount for all tables, you should be able to get it for some tables...right?
try using sys.dm_db_partition_stats DMV..
select
object_name(object_id) as tablename,sum(row_count) as totalrows
from sys.dm_db_partition_stats
where object_name(object_id) like 'Bb%'--gives tables count which start with bb*
group by object_id
This may not be accurate enough (very little deviation) when you have lot of inserts ,deletes and check the count immediately..
if you are bent on using sp_msforeach..
CREATE TABLE #counts
(
table_name varchar(255),
row_count int
)
EXEC sp_MSForEachTable #command1='INSERT #counts (table_name, row_count) SELECT ''?'', COUNT(*) FROM ?'
SELECT table_name, row_count FROM #counts where table_name like 'BB%' ORDER BY table_name, row_count DESC
References:
How to fetch the row count for all tables in a SQL SERVER database
If database contains heap or clusterd index tables then I would use one of following approaches:
1) sys.partitions.rows
SELECT s.name as schema_name, t.name as table_name, SUM(p.rows) AS SumOfRows
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.partitions p ON p.object_id = t.object_id
WHERE s.name = N'dbo' AND t.name LIKE N'BB%'
GROUP BY s.name, t.name
But rows column isn't accurate (according to MSDN).
2) Or, if I would like accurate numbers then I would use COUNT(*) thus
DECLARE #SqlStatement NVARCHAR(MAX) = N''
SELECT #SqlStatement =
#SqlStatement
+ N' UNION ALL SELECT '
+ '''' + full_name + ''''
+ N' AS full_name, COUNT(*) AS row_count FROM ' + full_name
FROM (
SELECT QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) AS full_name
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
WHERE s.name = N'dbo' AND t.name LIKE N'BB%'
) s
SET #SqlStatement = STUFF(#SqlStatement, 1, 10, N'')
EXEC sp_executesql #SqlStatement

Search column name having specific value in tables in certain database

Is there any way I can search a column having specific value I am trying to find through all tables in a database?
For example I have
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%VersionID%'
ORDER BY schema_name, table_name;
Which I found from searching. It gives me the table names that "versionID" column exists, but how can I search to return table names that for example have a value of "35" for that column.
Thanks in advance,
I apologize, maybe I am not being clear in my request. Maybe this cannot be done in SQL because I have not found anything through my research. But let me clarify.
Running this script
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%factor%'
--and table_name in (Select name from sysobjects where ratingVersionID = 35)
ORDER BY schema_name, table_name;
Will return this for example:
But let say, the "factor" column in "AutoAge_Factor" table does NOT HAVE any records matching to "35". How can I eliminate that table from returning in the results. But I would really prefer the format of the results be this way because I would like to use this return as a loop and do some other stuff within the loop.
Thanks again!
This modification to your sql will generate more SQL that you can run
SELECT
'select '''+SCHEMA_NAME(schema_id) +'.'+t.name + ''', '+c.name + ' from '
+ SCHEMA_NAME(schema_id) +'.' + t.name
+ ' where ' + c.name + ' = 35'
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%ID%'
ORDER BY schema_name(schema_id), t.name
You could make the SQL run automatically if necessary, but the syntax for that depends on your platform. Alternatively, copy the results into your query tool and run them, if that suffices
select s.name, c.name from sys.columns c inner join sys.tables s
on s.object_id = c.object_id where c.name like'%35%'
This will give you the columns with 35 and the associated table.
declare #tableName varchar(100), #colName varchar(100) declare
#sqlStatement nvarchar(100)
declare tablelist cursor for select s.name, c.name from sys.columns
c inner join sys.tables s on s.object_id = c.object_id where c.name
like'%YourSearchCondtion%' OPEN tablelist FETCH NEXT FROM tablelist
into #tableName, #colName
while ##FETCH_STATUS = 0 BEGIN
SELECT #sqlStatement = 'SELECT ' + #colName + ', * FROM ' + #tableName
+ ' WHERE ' + #colName + ' NOT LIKE ''%35%'''
exec sp_executesql #sqlStatement
-- Here you can get the table that you dont want and add to a temp table.. PRINT CAST(##ROWCOUNT AS VARCHAR)
FETCH NEXT FROM tablelist INTO #tableName, #colName END
CLOSE tablelist DEALLOCATE tablelist GO

sql select with column name like

I have a table with column names a1,a2...,b1.b2....
How can I select all those with column names like a%?
This will get you the list
select * from information_schema.columns
where table_name='table1' and column_name like 'a%'
If you want to use that to construct a query, you could do something like this:
declare #sql nvarchar(max)
set #sql = 'select '
select #sql = #sql + '[' + column_name +'],'
from information_schema.columns
where table_name='table1' and column_name like 'a%'
set #sql = left(#sql,len(#sql)-1) -- remove trailing comma
set #sql = #sql + ' from table1'
exec sp_executesql #sql
Note that the above is written for SQL Server.
You need to use view INFORMATION_SCHEMA.COLUMNS
select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = my_table_name AND COLUMN_NAME like 'a%'
TO inline rows you can use PIVOT and for execution EXEC() function.
This will show you the table name and column name
select table_name,column_name from information_schema.columns
where column_name like '%breakfast%'
SELECT * FROM SysColumns WHERE Name like 'a%'
Will get you a list of columns, you will want to filter more to restrict it to your target table
From there you can construct some ad-hoc sql
Here is a nice way to display the information that you want:
SELECT B.table_catalog as 'Database_Name',
B.table_name as 'Table_Name',
stuff((select ', ' + A.column_name
from INFORMATION_SCHEMA.COLUMNS A
where A.Table_name = B.Table_Name
FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)')
, 1, 2, '') as 'Columns'
FROM INFORMATION_SCHEMA.COLUMNS B
WHERE B.TABLE_NAME like '%%'
AND B.COLUMN_NAME like '%%'
GROUP BY B.Table_Catalog, B.Table_Name
Order by 1 asc
Add anything between either '%%' in the main select to narrow down what tables and/or column names you want.
You cannot with standard SQL. Column names are not treated like data in SQL.
If you use a SQL engine that has, say, meta-data tables storing column names, types, etc. you may select on that table instead.
Blorgbeard had a great answer for SQL server. If you have a MySQL server like mine then the following will allow you to select the information from columns where the name is like some key phrase. You just have to substitute the table name, database name, and keyword.
SET #columnnames = (SELECT concat("`",GROUP_CONCAT(`COLUMN_NAME` SEPARATOR "`, `"),"`")
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='your_database'
AND `TABLE_NAME`='your_table'
AND COLUMN_NAME LIKE "%keyword%");
SET #burrito = CONCAT("SELECT ",#columnnames," FROM your_table");
PREPARE result FROM #burrito;
EXECUTE result;
Thank you #Blorgbeard for the genious idea.
By the way Blorgbeard's query was not working for me so I edited it:
DECLARE #Table_Name as VARCHAR(50) SET #Table_Name = 'MyTable' -- put here you table name
DECLARE #Column_Like as VARCHAR(20) SET #Column_Like = '%something%' -- put here you element
DECLARE #sql NVARCHAR(MAX) SET #sql = 'select '
SELECT #sql = #sql + '[' + sys.columns.name + '],'
FROM sys.columns
JOIN sys.tables ON sys.columns.object_id = tables.object_id
WHERE sys.columns.name like #Column_Like
and sys.tables.name = #Table_Name
SET #sql = left(#sql,len(#sql)-1) -- remove trailing comma
SET #sql = #sql + ' from ' + #Table_Name
EXEC sp_executesql #sql