Hi guys my basic sql knowledge needs some help
I want to be able to replace a variable value with a value in a table and keep running the query until the end value in the table is reached
start query
DECLARE #prime_SCHEMA VARCHAR(20)
DECLARE #next_SCHEMA VARCHAR(20)
DECLARE #TABLE_name VARCHAR(100)
DECLARE #SQL VARCHAR(500)
SET #prime_SCHEMA = 'aaa'
SET #next_SCHEMA = 'bbb'
SET #TABLE = 'table1'
SET #sql = 'select top 1 * into '+#next_SCHEMA +'.'+#TABLE_name +' from '+#prime_SCHEMA +'.'+#TABLE_name +' TRUNCATE TABLE '+#next_SCHEMA +'.'+#TABLE_name
print #sql
I now want to wrap this in a Fetch and use a table called 'table_val' to update the TABLE_name value
and loop around till all the rows have been used in the table
so effectively i could end up with multiple #sql statements
thanks
Try this one -
Query:
DECLARE
#prime_schema SYSNAME = 'aaa'
, #next_schema SYSNAME = 'bbb'
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT CHAR(13) + '
SELECT *
INTO [' + #next_schema + '].[' + o.name + ']
FROM [' + s.name + '].[' + o.name + ']
WHERE 1 != 1'
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
WHERE o.[type] = 'U'
AND s.name = #prime_schema
AND o.name IN ('table1', 'table2', 'table3')
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #SQL
Output:
SELECT *
INTO [bbb].[table1]
FROM [aaa].[table1]
WHERE 1 != 1
SELECT *
INTO [bbb].[table2]
FROM [aaa].[table2]
WHERE 1 != 1
SELECT *
INTO [bbb].[table3]
FROM [aaa].[table3]
WHERE 1 != 1
Related
I need to prepare a dynamic query to find the length of all the rows in a column in sql server. let say if there are 10 columns for a table with 100 rows. I need to find the row length for each column dynamically.
Assuming that your all columns are string columns, though len function should work anyways.
-- replace 'mytable' with the actual table name
declare #tableName nvarchar(128) = 'mytable';
declare #queryToRun nvarchar(max) = '';
-- IMPORTANT: following query is putting each column name as len_columnName
select #queryToRun = #queryToRun + ', len([' + c.name + ']) as [len_' + c.name + ']
'
from sys.tables as t
inner join sys.columns as c on t.object_id = c.object_id
where t.name = #tableName
-- removing the first comma
set #queryToRun = SUBSTRING(#queryToRun, 2, len(#queryToRun) - 1);
-- creating the query with dynamic column names
set #queryToRun = 'select ' + #queryToRun + ' from ' + #tableName;
--print #queryToRun
exec (#queryToRun)
you can use sys.tables and sys.all_columns
declare #Sql nvarchar(max)='select '
select #Sql=#sql+'Sum(len('+QUOTENAME(c.name)+')) as Len'+QUOTENAME(c.name)+',' from sys.tables t join sys.all_columns c on t.object_id=c.object_id
where t.Name='YourTableName'
set #Sql = left(#Sql,len(#sql)-1)+' from YourTableName'
select #Sql
Try this Script you will get data length of each columns in table dynamically
IF OBJECT_ID('dbo.LenghtOfRows')IS NOT NULL
DROP TABLE LenghtOfRows
CREATE TABLE LenghtOfRows (
Id Int IDENTITY,
Sqlode nvarchar(max)
)
DECLARE #SQL NVARCHAR(max),
#MinId INT,
#MaxId INT,
#tableName Varchar(100) ='StudentLabExamScore', --Give Table name here
#GetSQL NVARCHAR(max)
SET #SQL = 'SELECT ''SELECT DATALENGTH(''+COLUMN_NAME+'') As Len_'' +COLUMN_NAME +'' FROM ''+TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '''+#tableName+''''
PRINT #SQL
INSERT INTO LenghtOfRows(Sqlode)
EXEC ( #SQL)
SELECT #MinId = MIN(Id) from LenghtOfRows
SELECT #MaxId = MAX(Id) from LenghtOfRows
WHILE (#MInId <=#MaxId)
BEGIN
SELECT #GetSQL= Sqlode FROM LenghtOfRows WHERE id=#MInId
EXEC (#GetSQL)
PRINT #GetSQL
SET #MInId=#MInId+1
END
Goal is to get all UNIQUEIDENTIFIER values from all columns in database.
Code which is supposed to load all those values:
DECLARE #TableNames TABLE
(
ID INT NOT NULL IDENTITY(0, 1),
TableName NVARCHAR(50) NOT NULL,
ColName NVARCHAR(50) NOT NULL
);
DECLARE #Guids TABLE
(
ID INT NOT NULL IDENTITY(0, 1),
FoundGuid UNIQUEIDENTIFIER NOT NULL
);
DECLARE #Local NVARCHAR(50);
WHILE #Counter < 500
BEGIN
SELECT #Local = TableName FROM #TableNames WHERE Id = #Counter;
INSERT INTO #Guids EXEC('SELECT Id FROM [' + #Local + ']');
SET #Counter = #Counter + 1;
END;
Is this safe thing to do so? Eventually, what is the way to get those values?
I would use the system views to generate dynamic sql. This is 100% accurate and not limited to only those columns named Id. It won't matter what schema or column name is used. This will get you all those values with no looping at all.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'select ' + QUOTENAME(c.name) + ' = ' + QUOTENAME(c.name)
+ ' FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
+ ' UNION ALL '
from sys.tables t
join sys.columns c on c.object_id = t.object_id
join sys.types ty on ty.user_type_id = c.user_type_id
join sys.schemas s on s.schema_id = t.schema_id
where ty.name = 'uniqueidentifier'
--removes the last UNION ALL
select #SQL = left(#SQL, len(#SQL) - 10)
select #SQL
--uncomment below to execute the dynamic sql when you are comfortable it is correct
--exec sp_executesql #SQL
How to select columns in a table that only contain a specific value for all the rows? I am trying to find these columns to do an update on those values with a NULL value. In my columns I have varied range of values including NA
I am using SQL Server 2012.
I've tried doing: thsi only gives me column names. Can i add to this condition for columns with value 'NA'?
SELECT COLUMN_NAME AS NAMES,COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'ABC'
I am a beginner in SQL. Trying to figure out how to do this.
If min of column equals to max then that column contains same values:
Select
case when min(col1) = max(col1) then 1 else 0 end as Col1IsSame,
case when min(col2) = max(col2) then 1 else 0 end as Col2IsSame,
...
from Table
With dynamic query:
declare #s nvarchar(max) = 'select '
select #s = #s + 'case when min(' + COLUMN_NAME + ') = max(' +
COLUMN_NAME + ') then 1 else 0 end as ' + COLUMN_NAME + ','
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'Table'
Set #s = substring(#s, 1, len(#s) - 1) + ' from Table'
exec(#s)
TRY THIS QUERY
DECLARE #SQLQUERY NVARCHAR(MAX)
declare #tableName varchar(50)
DECLARE #NAME VARCHAR(50)
Declare #ParamDefinition AS NVarchar(2000)
Set #ParamDefinition = '#OIM VARCHAR(20)'
SELECT NAME
FROM sys.objects
WHERE [object_id]=#OIM
set #tableName= (SELECT NAME
FROM sys.objects
WHERE [object_id]=#OIM)
SET #NAME=(SELECT C.NAME
FROM sys.columns c
JOIN
sys.tables t ON c.object_id = t.object_id
WHERE c.name in (select distinct name
from sys.columns
where object_id=#OIM))
SET #SQLQUERY = ''
SELECT #SQLQUERY = #SQLQUERY + 'UPDATE ' + #tableName + ' SET ' + #NAME + ' = NULL WHERE ' + #NAME + ' = NA ; '
PRINT #SQLQUERY
Execute sp_Executesql #SQLQUERY , #ParamDefinition, #OIM
end
So I looked this up and this question is very similar but it's missing a key piece: SQL Server count number of distinct values in each column of a table
So in that question they want the distinct count for each column. What I am looking to do is to get a count of each distinct value for each column in a table (and I'm doing this for all the tables in a particular database which is why I'm looking to try to automate this as much as possible). Currently my code looks like this which I have to run for each column:
select mycol1, COUNT(*) as [Count]
from mytable
group by mycol1
order by [Count] desc
Ideally my output would look like this:
ColumnName1 Count
val1 24457620
val2 17958530
val3 13350
ColumnName2 Count
val1 24457620
val2 17958530
val3 13350
val4 12
and so on for all the columns in the table
This answer below (provided by #beargle) from that previous question is really close to what I'm looking to do but I can't seem to figure out a way to get it to work for what I am trying to do so I would appreciate any help.
DECLARE #Table SYSNAME = 'TableName';
-- REVERSE and STUFF used to remove trailing UNION in string
SELECT REVERSE(STUFF(REVERSE((SELECT 'SELECT ''' + name
+ ''' AS [Column], COUNT(DISTINCT('
+ QUOTENAME(name) + ')) AS [Count] FROM '
+ QUOTENAME(#Table) + ' UNION '
-- get column name from sys.columns
FROM sys.columns
WHERE object_id = Object_id(#Table)
-- concatenate result strings with FOR XML PATH
FOR XML PATH (''))), 1, 7, ';'));
You could use:
DECLARE #Table SYSNAME = 'TableName';
DECLARE #SQL NVARCHAR(MAX) = ''
SELECT #SQL = STUFF((SELECT ' UNION SELECT ''' + name
+ ''' AS [Column], '
+ 'CAST(' + QUOTENAME(Name)
+ ' AS NVARCHAR(MAX)) AS [ColumnValue], COUNT(*) AS [Count] FROM '
+ QUOTENAME(#Table) + ' GROUP BY ' + QUOTENAME(Name)
FROM sys.columns
WHERE object_id = Object_id(#Table)
-- concatenate result strings with FOR XML PATH
FOR XML PATH ('')), 1, 7, '');
EXECUTE sp_executesql #SQL;
Which will produce SQL Like the following for a table with two columns (Column1 and Column2)
SELECT 'Column1' AS [Column],
CAST([Column1] AS NVARCHAR(MAX)) AS [ColumnValue],
COUNT(*) AS [Count]
FROM [TableName]
GROUP BY [Column1]
UNION
SELECT 'Column2' AS [Column],
CAST([Column2] AS NVARCHAR(MAX)) AS [ColumnValue],
COUNT(*) AS [Count]
FROM [TableName]
GROUP BY [Column2]
EDIT
If you want a new result set for each column then use:
DECLARE #Table SYSNAME = 'TableName';
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL = (SELECT ' SELECT ' + QUOTENAME(Name)
+ ', COUNT(*) AS [Count] FROM '
+ QUOTENAME(#Table) + ' GROUP BY ' + QUOTENAME(Name) + ';'
FROM sys.columns
WHERE object_id = Object_id(#Table)
-- concatenate result strings with FOR XML PATH
FOR XML PATH (''));
EXECUTE sp_executesql #SQL;
Which would produce SQL Like:
SELECT [Column1],
COUNT(*) AS [Count]
FROM [callsupplier]
GROUP BY [Column1];
SELECT [Column2],
COUNT(*) AS [Count]
FROM [callsupplier]
GROUP BY [Column2];
thought i would take a stab at this whilst waiting for a backup to restore
hope this does what you require
create Table #Temp
(tableName varchar(100),
columnName varchar(100),
value varchar(1000),
distinctItems int)
Declare #tabName as varchar(100)
Declare #colName as varchar(100)
Declare #tabid as int
Declare cursorTables Cursor
for
select t.object_id , t.name , c.name from sys.tables t inner join sys.columns c on t.object_id = c.object_id
open cursorTables
Fetch Next from cursorTables into
#tabid,#tabName,#colName
while ##Fetch_Status = 0
Begin
declare #query as nVarchar(1000)
set #query = 'Insert into #Temp SELECT ''' + #tabName + ''' , '''+ #colName +''', ' + #colName + ', COUNT([' + #colName +']) AS Expr1 FROM [' + #tabName+ '] group by [' + #colName + ']'
print #query
exec sp_executesql #query
Fetch Next from cursorTables into
#tabid,#tabName,#colName
End
Close cursorTables
Deallocate cursorTables
select * from #temp
drop table #temp
produces some not very useful results on PK values and i suspect it would not work on columns greater than varchar(1000) but works on a fe of my dbs
This version makes a good snippet:
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += 'SELECT ''' + t.name + ''', ''' + c.name + ''', ' + c.name + ', COUNT(' + c.name + ') AS C FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' GROUP BY ' + c.name + ';' + CHAR(13)
FROM sys.tables AS t
INNER join sys.columns c on t.object_id = c.object_id
INNER JOIN sys.schemas AS s ON t.[schema_id] = s.[schema_id]
WHERE s.name LIKE 'stage' AND t.name LIKE 'table' AND c.name LIKE '%whatever%';
--PRINT #sql;
EXEC sp_executesql #sql
I have table name as #Table_Name
I have column value as #Value but don't have the column name (but that exist at 1st position and can be Seek_id or prov_id ...I have to compare my value with this id )
How can I compare that table column name value ?
I want something like
SELECT * FROM #Table_Name
WHERE Table.Column[1].Value = #Value
for example #Table_Name = bb_match and #Value = 6
Possible this be helpful for you -
Query:
IF OBJECT_ID (N'dbo.bb_match') IS NOT NULL
DROP TABLE dbo.bb_match
CREATE TABLE dbo.bb_match (seek_id INT, prov_id INT)
INSERT INTO dbo.bb_match (seek_id, prov_id)
VALUES (6, 1), (2, 6)
DECLARE
#ColumnID TINYINT
, #Value INT
, #TableName SYSNAME
, #SQL NVARCHAR(500)
SELECT
#ColumnID = 1
, #Value = 6
, #TableName = 'dbo.bb_match'
SELECT #SQL = 'SELECT * FROM ' + #TableName + ' WHERE [' + c.name + '] = ' + CAST(#Value AS NVARCHAR(MAX))
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
JOIN sys.columns c WITH (NOWAIT) ON o.[object_id] = c.[object_id]
WHERE o.[type] = 'U' -- <-- only for tables columns
AND s.name + '.' + o.name = #TableName
AND c.column_id = #ColumnID
PRINT #SQL
EXEC sp_executesql #SQL
Shorter, but unsafe (sys.columns contains column_name for tables, views, procedures, ...):
SELECT #SQL = 'SELECT * FROM ' + #TableName + ' WHERE [' + c.name + '] = ' + CAST(#Value AS NVARCHAR(MAX))
FROM sys.columns c WITH (NOWAIT)
WHERE c.[object_id] = OBJECT_ID(#TableName)
AND c.column_id = #ColumnID
EXEC sys.sp_executesql #SQL
Output:
SELECT * FROM dbo.bb_match WHERE [seek_id] = 6
Results:
seek_id prov_id
----------- -----------
6 1
declare #sql varchar(MAX)
declare #tablename varchar(100) = 'MyTable' --add your table name here
declare #value varchar(100) = 'SomeValue' -- add your desired value hree
select #sql = 'SELECT * FROM ' + #tablename + ' WHERE '
+ name
+ ' = ''' + #value + ''''
from sys.columns where object_id = object_id(#tablename) and column_id = 1
exec (#sql)
There are three parts to this. First I'm declaring three strings. #sql is where I will build up the query, #tablename and #value are the table and search value to look in/for. I've put in the dummy values MyTable and SomeValue to show what I'm talking about
Next I build up the sql statement. The first line sets the string as SELECT * FROM MyTable WHERE
I then add in the column name by selecting Name from the SQL SERver system table sys.columns, filtering on the first column (column_id = 1) and the table name
The next step is to add the value we want to search for in the column.
Finally, EXEC(#sql) interprets the string as a command and runs it.