SQL get dynamic query result into another query - sql

I would like to get, for each line, the result of my ReqCount query directly into my main SELECT
(the main query is simplified on purpose).
I've tried using the EXEC sp_executesql but it was unsuccessful.
How can I manage to do this?
BEGIN
SELECT DISTINCT
TBL.name AS TableName
, IDX.type_desc
, COL.name
, 'SELECT MAX(occurs) FROM (SELECT ' + COL.name + ', count(*) as occurs FROM ' + TBL.name
+ ' GROUP BY ' + COL.name + ') a' as ReqCount
FROM sys.tables AS TBL
INNER JOIN sys.schemas SCH ON TBL.schema_id = SCH.schema_id AND TBL.name <> 'sysdiagrams'
INNER JOIN sys.indexes IDX ON TBL.object_id = IDX.object_id AND IDX.type = 0
LEFT JOIN sys.columns COL ON COL.object_id = TBL.object_id AND (COL.name LIKE '%id' OR COL.name LIKE '%code')
END
TableName type_desc name ReqCount
t_intervention_instruction HEAP NULL NULL
t_constat HEAP con_code SELECT MAX(occurs) FROM (SELECT con_code, count(*) as occurs FROM t_constat GROUP BY con_code) a
t_cri_clientele HEAP NULL NULL
t_ope_sur_branchement HEAP osb_id SELECT MAX(occurs) FROM (SELECT osb_id, count(*) as occurs FROM t_ope_sur_branchement GROUP BY osb_id) a

Related

Trying to create a table of table names and max values

In SQL Server, we have a number of tables, all containing a field last_modified that records when a particular record was created, modified, or flagged for deletion. I want to create a table of table names and the max() value of last_modified.
I'm brute forcing it as follows:
I run a query modified from Query to list number of records in each table in a database to list tables that have rows and eliminate some internal tables.
SELECT
t.NAME AS TableName,
p.[Rows]
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE
t.NAME NOT LIKE 'dt%' AND t.name not like '%ml%' and
t.NAME not in ('OrderHeaders', 'OrderHeaderExtendedText', 'OrderLIDetails', 'OrderLIDetailExtendedText', 'UserCustomerXRef', 'UserDetails', 'UserDetailExtendedText', 'UserTypeDescription') and
p.rows <> 0 and
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, p.[Rows]
ORDER BY
TableName
This gives me a table like this:
Then I paste this output into Excel and create a series of queries there:
A2.value reads BidCustomerXRef. C2.Value reads ="select top 1 last_modified, '" & A2 & "' as 'Table' from " & A2 & " where deleted = 'N' order by last_modified desc" and so I get
select top 1 last_modified, 'BidCustomerXRef' as 'Table'
from BidCustomerXref
where deleted = 'N'
order by last_modified desc`
So I copy all of those rows to my SQL query window and I get this:
What I want is a single table that looks like this:
TableName
last_modified
BidCustomerXRef
2022-06-21 21:30:07.287
Bids
2022-06-22 20:00:06.383
CustomerARDetail
2022-06-22 18:00:11.923
etc.
Here is one way you can do this. I am using the system tables to generate dynamic sql instead of using a dreaded cursor or other sort of iteration going row by agonizing row.
declare #sql nvarchar(max) = ''
select #sql += 'select TableName = ''' + s.name + '.' + t.name + ''', last_modified = (select max(last_modified) from ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' where deleted = ''N'') union all '
from sys.tables t
join sys.schemas s on s.schema_id = t.schema_id
join sys.indexes i ON t.object_id = i.object_id
join sys.partitions p ON i.object_id = p.object_id and i.index_id = p.index_id
where t.NAME NOT LIKE 'dt%'
and t.name not like '%ml%'
and t.NAME not in ('OrderHeaders', 'OrderHeaderExtendedText', 'OrderLIDetails', 'OrderLIDetailExtendedText', 'UserCustomerXRef', 'UserDetails', 'UserDetailExtendedText', 'UserTypeDescription')
and p.rows > 0
and i.object_id > 255
and i.index_id <= 1
order by t.name
select #sql = left(#sql, len(#sql) - 9) --removes the last UNION ALL
select #sql
--uncomment the line below once you have evaluated that the dynamic sql is correct
--exec sp_executesql #sql

Get all tables from database, if the table has some records present

Is there any way to get all the tables, with a condition that if table is not empty(if it has some records present).
I can get the list of tables with :
USE 'DatabaseName'
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_Schema = 'dbo'
ORDER BY table_NAME.
But, I want something like
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_Schema = 'dbo'
AND "**table has some records present**" ORDER BY table_NAME
Try :
SELECT
OBJECT_NAME(T.OBJECT_ID) AS TABLE_NAME,
SUM(P.ROWS) AS TOTAL_ROWS
FROM
sys.tables T
INNER JOIN
sys.partitions P
ON T.OBJECT_ID = P.OBJECT_ID
WHERE
P.INDEX_ID IN (0,1)
GROUP BY
T.OBJECT_ID
HAVING
SUM(P.ROWS) > 0
run this
select 'select count(*) [entries],'''+ TABLE_NAME + ''' from '+ quotename(TABLE_SCHEMA) + '.' + quotename(TABLE_NAME) + ' union' from INFORMATION_SCHEMA.TABLES
to get a list of every table and the number of entries in that table then you can put that into a temp table and look for anything where entries >1.
Remember to remove the union at the end.
select * from
(
SELECT sc.name +'.'+ ta.name TableName
,SUM(pa.rows) RowCnt
FROM sys.tables ta
INNER JOIN sys.partitions pa
ON pa.OBJECT_ID = ta.OBJECT_ID
INNER JOIN sys.schemas sc
ON ta.schema_id = sc.schema_id
WHERE ta.is_ms_shipped = 0 AND pa.index_id IN (1,0)
GROUP BY sc.name,ta.name
ORDER BY SUM(pa.rows) DESC
) as T where RowCnt>0
More help can get you from here

Create Sql Server view using table name from sysobjects table

I have around 200 tables. I want to create a view from all these tables. I feel it is inefficient to hardcode all the table names and do an UNION ALL in the view definition.
Instead I am planning to retrieve the table name from sysobjects table like
Select name from sysobjects where name like 'Warehouse_Inventory%'
How can I use these table names and create a view out of it?
Note: I am selecting only 10 columns which are common. If any column is not present in a table, I want to display NULL for it.
This Query may help you..
SELECT 'CREATE VIEW VIEW_NAME AS'
UNION ALL
SELECT 'SELECT * FROM ['+NAME+']
UNION ALL' FROM SYS.TABLES where name like 'Warehouse_Inventory%'
I am not sure why you want to use sys.sysojects instead of other sys views. Also now sure why when you want to union all tables you would want to search by a table name..... I would probably recommend a cursor on tables and temp tables to hold your results if you have 200 tables just do to size of the query but if you really really want to do it via union all here is a way...
Build a list of the 10 columns you want. Then run the query. you may need to tweak and add some cast/convert function to ensure everything is the right datatypes this can be done dynamically with sys.types and sys.columns or just make sure everything is a NVARCHAR(???) by altering my dynamic sql below and move forward.
DECLARE #ListOfColumns AS TABLE (ColumnName VARCHAR(100))
INSERT INTO #ListOfColumns (ColumnName) VALUES ('col1'),('col2'),('col3')
DECLARE #SQLStatement NVARCHAR(MAX)
;WITH cteColumnsTableCross AS (
SELECT
SchemaName = s.name
,t.schema_id
,TableName = t.name
,l.ColumnName
FROm
#ListOfColumns l
CROSS JOIN sys.tables t
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
)
, cteColumns AS (
SELECT
x.SchemaName
,x.TableName
,x.ColumnName
,ColumnExists = IIF(c.name IS NOT NULL,1,0)
,RowNum = ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY x.TableName DESC)
--you can add data type by getting from sys.columns and sys.types if desired
FROM
cteColumnsTableCross x
LEFT JOIN sys.tables t
ON x.TableName = t.name
AND x.schema_id = t.schema_id
LEFT JOIN sys.columns c
ON t.object_id = c.object_id
AND x.ColumnName = c.name
)
, cteSelectStatements AS (
SELECT
TableName = t.name
,TableSelect = 'SELECT TableName = ''' + t.name + ''', ' +
STUFF(
(SELECT ', ' + c.ColumnName + ' = ' + IIF(c.ColumnExists = 0,'NULL',c.ColumnName)
FROM
cteColumns c
WHERE t.name = c.Tablename
FOR XML PATH(''))
,1,1,'')
+ ' FROM ' + t.name +
IIF((ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY t.name DESC)) > 1,' UNION ALL ','')
FROM
sys.tables t
)
SELECT #SQLStatement = STUFF(
(SELECT ' ' + TableSelect
FROM
cteSelectStatements
ORDER BY
TableName
FOR XML PATH(''))
,1,1,'')
PRINT #SQLStatement
--EXECUTE #SQLStatement

Query to find out if foreign key is referenced anywhere else in the database

I have table Animal.
I want to return everything from this table + one column which denotes if record is referenced anywhere else as a foreign key.
I.E.:
Animal_Id Name
1 Cat
2 Dog
3 Parrot
I want to return this:
AnimalId Name Referenced
1 Cat true
2 Dog false
3 Parrot true
by 'referenced' I mean if a specific Animal_Id was referenced in any other table in the database as a foreign key. I think I first can query information_schema and find out what tables contain this foreign key and then use loop and dynamic sql to execute
select count(*) from eachTable where AnimalID = 1
Does anyone have a snippet on how to do that?
This should do it:
SELECT OO.Animal_ID, OO.Name, CASE WHEN XX.REFERENCED IS NULL THEN 'false' ELSE 'true' END Referenced
FROM Animal OO
OUTER APPLY (SELECT SUM(1) REFERENCED
FROM (SELECT FkAnimal_ID FROM AnimalRef1 RR WHERE RR.FkAnimal_ID = OO.Animal_ID UNION ALL
SELECT FkAnimal_ID FROM AnimalRef2 RR WHERE RR.FkAnimal_ID = OO.Animal_ID UNION ALL
SELECT FkAnimal_ID FROM AnimalRef3 RR WHERE RR.FkAnimal_ID = OO.Animal_ID) II) XX
If you don't know all the FK tables, you can use system meta-data tables to generate that collection of UNION ALL queries into a table, which you could then copy & paste into your query:
WITH AKT AS ( SELECT f.name AS ForeignKey
,OBJECT_NAME(f.parent_object_id) AS TableName
,COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName
,OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName
,COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
WHERE f.referenced_object_id = object_id('Animal'))
SELECT 'SELECT ' + ColumnName + ' FROM ' + TableName + ' WHERE RR.' + ColumnName + ' = OO.' + ReferenceColumnName + ' UNION ALL'
FROM AKT
And for the whole thing in a single query using a recursive CTE:
DECLARE #QUERY NVARCHAR(MAX)
WITH AKT AS ( SELECT ROW_NUMBER() OVER (ORDER BY f.name) RN, f.name AS ForeignKey
,OBJECT_NAME(f.parent_object_id) AS TableName
,COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName
,SCHEMA_NAME(oo.schema_id) SchemaName
,OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName
,COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN sys.objects oo ON oo.object_id = fc.referenced_object_id
WHERE f.referenced_object_id = object_id('Animal'))
,bs AS (SELECT AKT.RN
,'SELECT ' + ColumnName + ' FROM ' + SchemaName + '.' + TableName + ' WHERE ' + ColumnName + ' = OO.' + ReferenceColumnName SubQuery
FROM AKT)
,re AS (SELECT bs.RN, CAST(RTRIM(bs.SubQuery) AS VARCHAR(MAX)) Joined
FROM bs
WHERE bs.RN = 1
UNION ALL
SELECT bs2.RN, CAST(re.Joined + ' UNION ALL ' + ISNULL(RTRIM(bs2.SubQuery), '') AS VARCHAR(MAX)) Joined
FROM re, bs bs2
WHERE re.RN = bs2.RN - 1 )
,fi AS (SELECT ROW_NUMBER() OVER (ORDER BY RN DESC) RNK, Joined
FROM re)
SELECT #QUERY = 'SELECT OO.Animal_ID, OO.Name, CASE WHEN XX.REFERENCED IS NULL THEN ''No'' ELSE ''Yes'' END Referenced
FROM Animal OO
OUTER APPLY (SELECT SUM(1) REFERENCED
FROM (' + Joined + ') II) XX'
FROM fi
WHERE RNK = 1
EXEC (#QUERY)

SQL Server search for a column by name

I'm doing some recon work and having to dig through a few hundred SQL Server database tables to find columns.
Is there a way to easily search for columns in the database and return just the table name that the column belongs to?
I found this, but that also returns Stored procedures with that column name in it...
SELECT OBJECT_NAME(object_id) FROM sys.columns WHERE name = 'foo'
This includes views though but can be further filtered . It may be useful though.
More generally...
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'foo'
sys.columns
To get the
1) full column name
2) object name (including schema)
3) object type (table/view)
4) data type (nice format: varchar(6) or numeric(5,2), etc.)
5) null/not null
6) information on identity, check constraint, and default info
try this:
DECLARE #Search varchar(200)
SET #Search='YourColumnName' --can be a partial or a complete name
SELECT
s.name as ColumnName
,sh.name+'.'+o.name AS ObjectName
,o.type_desc AS ObjectType
,CASE
WHEN t.name IN ('char','varchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length) END+')'
WHEN t.name IN ('nvarchar','nchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length/2) END+')'
WHEN t.name IN ('numeric') THEN t.name+'('+CONVERT(varchar(10),s.precision)+','+CONVERT(varchar(10),s.scale)+')'
ELSE t.name
END AS DataType
,CASE
WHEN s.is_nullable=1 THEN 'NULL'
ELSE 'NOT NULL'
END AS Nullable
,CASE
WHEN ic.column_id IS NULL THEN ''
ELSE ' identity('+ISNULL(CONVERT(varchar(10),ic.seed_value),'')+','+ISNULL(CONVERT(varchar(10),ic.increment_value),'')+')='+ISNULL(CONVERT(varchar(10),ic.last_value),'null')
END
+CASE
WHEN sc.column_id IS NULL THEN ''
ELSE ' computed('+ISNULL(sc.definition,'')+')'
END
+CASE
WHEN cc.object_id IS NULL THEN ''
ELSE ' check('+ISNULL(cc.definition,'')+')'
END
AS MiscInfo
FROM sys.columns s
INNER JOIN sys.types t ON s.system_type_id=t.system_type_id and t.is_user_defined=0
INNER JOIN sys.objects o ON s.object_id=o.object_id
INNER JOIN sys.schemas sh on o.schema_id=sh.schema_id
LEFT OUTER JOIN sys.identity_columns ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id
LEFT OUTER JOIN sys.computed_columns sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id
LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id
WHERE s.name LIKE '%'+#Search+'%'
select c.name as ColumnName, o.name as TableName
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
where c.name = 'MyColumnName'
http://www.red-gate.com/products/SQL_Search/index.htm?utm_source=google&utm_medium=cpc&utm_content=brand_aware&utm_campaign=sqlsearch&gclid=COSfqe_mmKQCFSE1gwodSxOrEQ
This should do it for you. I use it everyday.
This stored procedure will search for table.name and column.name pairs.
I use when I have "WhateverId" in code and I want to know where that is (probably) stored in the database without actually having to read through and understand the code. :)
CREATE OR ALTER PROC FindColumns
#ColumnName VARCHAR(MAX) = NULL,
#TableName VARCHAR(MAX) = NULL
AS
SELECT T.[name] AS TableName, C.[name] AS ColumnName
FROM sys.all_columns C
JOIN sys.tables T ON C.object_id = T.object_id
JOIN sys.types CT ON C.user_type_id = CT.user_type_id
WHERE (#ColumnName IS NULL OR C.[name] LIKE '%' + TRIM(#ColumnName) + '%')
AND (#TableName IS NULL OR T.[name] LIKE '%' + TRIM(#TableName) + '%')
ORDER BY T.[name], C.[name]
select table_name from information_schema.columns
where column_name = '<your column name here>'
Using the information_schema views is 'more correct' as system details in the system databases are subject to change between implementations of SQL Server.