Using Dynamically built query in SQL View - sql-server

I have this view:
SELECT CAST([IDNumber] AS varchar) AS IDNumber
FROM [ViewXTimeData1]
UNION
SELECT CAST([IDNumber] AS varchar) AS IDNumber
FROM [ViewXTimeData2]
UNION
SELECT CAST([IDNumber] AS varchar) AS IDNumber
FROM [ViewXTimeData3]
UNION
SELECT CAST(vVisitorID AS varchar) AS IDNumber
FROM [dbo].[tblVisitor]
The purpose of this view is to pull data from the 3 linked databases and the local database. I have a view of each that I then call in the main view (ViewXTimeDataAll).
Now what happened was that ViewXTimeData2's database went offline, due to connectivity issues, this crashed the view and the application could not get any info from ViewXTimeDataAll.
So what I did was I created this:
DECLARE #GETVIEWS NVARCHAR(2000);
SET #GETVIEWS = ''
IF Exists(select top(1) * from SZAAGATAA01.Xtime900.dbo.LSCTagLookup)
SET #GETVIEWS = #GETVIEWS + 'SELECT CAST([IDNumber] AS varchar) AS IDNumber FROM [ViewXTimeDataAGA] UNION '
IF Exists(select top(1) * from SZADELTAA01.Xtime900.dbo.LSCTagLookup)
SET #GETVIEWS = #GETVIEWS + 'SELECT CAST([IDNumber] AS varchar) AS IDNumber FROM [ViewXTimeDataCHO] UNION '
IF Exists(select top(1) * from SZADELTAA01.Xtime900.dbo.LSCTagLookup)
SET #GETVIEWS = #GETVIEWS + 'SELECT CAST([IDNumber] AS varchar) AS IDNumber FROM [ViewXTimeDataDEL] UNION '
SET #GETVIEWS = #GETVIEWS + 'SELECT CAST(vVisitorID AS varchar) AS IDNumber FROM [dbo].[tblVisitor]'
EXEC(#GETVIEWS);
Works great. If the database is offline it omits it and still gets the information from the available databases, which is exactly what I need... BUT can't use variables in a View (I find out after writing this...).
Should add that I need to filter the data, hence the reason I put everything in a view.

Related

How to Pass Tablename, Fieldnames, Values as perameters in Stored Procedure using CI?

I am developing a custom application using CodeIgniter and MSSQL Server. Here i am using stored procedures.
Now i am wondering to implement codeigniter query type functionality where i can create a universal stored procedure in SQL Server and at the time of using i can pass tablename, array of fields and values.
It can work for both insert and update.
Something like we do in CodeIgniter to execute the query,
$data = array('fieldname1' => 'value1',
'fieldname2' => 'value2');
$this->db->insert($tablename,$data);
Just like this if we can pass the table name and array of the data to stored procedure and stored procedure automatically execute it.
If this can be done, it can save lots n lots of man hours. If anyone have already done i will be very much happy to see the solution.
You need to make string very specific in this case.
Figure out your table name, Column name, Column values for insert. For update 2 more parameters are required Id column name and its value.
GO
---- exec InsertUpdate 'tablename', 'col1, col2, col3', 'val1, val2, val3', 'idcol', 'idval'
GO
Create proc InsertUpdate
( #TableName nvarchar(500),
#ColName nvarchar(max),
#ColValues nvarchar(max),
#IDColName nvarchar(100) = '', --- for update only otherwise null
#IdColValue nvarchar(Max) = '' --- for update only otherwise null
)
As
Begin
declare #Query nvarchar(max)
if (#IdColValue = '')
Begin
set #Query = ' Insert into ' + #TableName + ' (' + #ColName + ') values (' + #ColValues + ')'
End
Else
Begin
;with CtColumn as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColName,',') )
, CtValue as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColValues, ','))
, CTFinal as (
select CCOl.Slno, CCOl.Items as ColName, CVal.Items as ColValue from CtColumn as CCOl inner join CtValue as CVal on CCOl.Slno=CVal.Slno )
select #Query = 'update ' + #TableName + ' set ' +
stuff ( (select ',' + ColName + '=' + ColValue from CTFinal for xml path ('')) ,1,1,'') +
' where ' + #IDColName + '=' + #IdColValue
End
exec sp_executesql #Query
End
Go

string+ select query order by + string ;

I want output as get all tables from a database with name as 'T_'.
I have written the query ,it gets all the table name.
but I want no get the query as 'select count(*) from all tables in database union'
means I want to get
select count(*) from T1 UNION
select count(*) from T2 UNION
select count(*) from T3 UNION...
and so on
there are 1000 of rows so I want a query which will output the count(*) query itself.
select 'select count(*) from ' + table_name from INFORMATION_SCHEMA.TABLES where table_type='BASE TABLE'
and left(table_name,2) = 'T_'
order by TABLE_NAME
this query gives all select count(*) table names like T_*
select 'select count(*) from ' + table_name from INFORMATION_SCHEMA.TABLES where table_type='BASE TABLE'
and left(table_name,2) = 'T_'
order by TABLE_NAME
+'UNION';
Getting output
select count(*) from T_T1
select count(*) from T_T2
select count(*) from T_T3
expected output
select count(*) from T_T1 UNION
select count(*) from T_T2 UNION
select count(*) from T_T3 UNION
order by TABLE_NAME + ' UNION' means you want want to order by the value of TABLE_NAME with the sting UNION concatenated onto it (which will change nothing)
You need to put the UNION (I actually suggest UNION ALL here) in your SELECT: ...table_type='BASE TABLE' + N' UNION ALL '.
I also suggest changing table_name to QUOTENAME(table_name). Giving you a final query of:
SELECT N'SELECT COUNT(*) FROM' + QUOTENAME(TABLE_NAME) + NCHAR(13) + NCHAR(10) + N'UNION ALL'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND LEFT(TABLE_NAME, 2) = 'T_'
ORDER BY TABLE_NAME;
select 'select count(*) from ' + table_name + ' UNION ' from INFORMATION_SCHEMA ...

sql server linked oracle how to execute query with dataset

In sql server I have a table with id. I pass id through openquery in a loop.
while #coun < 1000
begin
select #id=id from #temp where num = #coun
#sql = 'select * from tableoracle where id=' + #id
execute('insert into #temp2 select * from openquery(ORAC, ' + #sql+')')
set #coun = #coun + 1
End
Can I send the id immediately as a set and not one by one?
if you access the entire table at once in oracle without id, the request hangs,
a lot of data
found the solution
declare #a varchar(max) = (select '(' + stuff (
(SELECT ',''' +id + ''''
FROM #temp
for xml path('')),
1, 1, '') + ')')
#sql = 'select * from tableoracle where id in ' + #a
execute('insert into #temp2 select * from openquery(ORAC, ' + #sql+')')

Get data from every column in every table in a database | SQL Server

I have seen multiple questions on how to retrieve every column from every table along with its data type, among many other pieces of information which can be summarised in the shortest way with this query:
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
However, is it possible to get all the data from the columns and the rows they belong to get the first row in the table alongside this? I have not found a way to do so thus far. Is it possible to do such, maybe also having a WHERE condition such as checking if the table contains a list of specific columns before returning it e.g.:
SELECT <AllTablesAndColumns+FirstRow>
FROM <WhereTheyCanBeSelectedFrom>
WHERE <TheTableHasTheseSpecificColumns>
Which would return the table name, column name and the data contained within those columns for each row.
If you are looking for more of an EAV structure
Let's say that we're looking for all tables with a column name of ZIPCODE
Example
Declare #S varchar(max) = ''
SELECT #S = #S +'+(Select top 1 SourceTable='''+A.Table_Name+''',* from '+quotename(A.Table_Name)+' for XML RAW)'
FROM INFORMATION_SCHEMA.COLUMNS A
Where COLUMN_NAME in ('ZipCode')
Declare #SQL varchar(max) = '
Declare #XML xml = '+stuff(#S,1,1,'')+'
Select SourceTable = r.value(''#SourceTable'',''varchar(100)'')
,Item = attr.value(''local-name(.)'',''varchar(100)'')
,Value = attr.value(''.'',''varchar(max)'')
From #XML.nodes(''/row'') as A(r)
Cross Apply A.r.nodes(''./#*'') AS B(attr)
Where attr.value(''local-name(.)'',''varchar(100)'') not in (''SourceTable'')
'
Exec(#SQL)
Returns
You could build dynamic query:
DECLARE #sql NVARCHAR(MAX) =
N'SELECT *
FROM (VALUES (1)) AS s(n)
<joins>';
DECLARE #joins NVARCHAR(MAX)= '';
SELECT #joins += FORMATMESSAGE('LEFT JOIN (SELECT TOP 1 * FROM %s ) AS sub%s
ON 1=1' + CHAR(10), table_schema + '.' + table_name,
CAST(ROW_NUMBER() OVER(ORDER BY 1/0) AS VARCHAR(10)))
FROM (SELECT DISTINCT table_schema, table_name
FROM INFORMATION_SCHEMA.COLUMNS
-- WHERE ... -- custom logic based on column type/name/...
) s;
SET #sql = REPLACE(#sql, '<joins>', #joins);
PRINT #sql;
EXEC(#sql);
DBFiddle Demo
The dynamic query has structure:
SELECT *
FROM (VALUES (1)) AS s(n) -- always 1 row
LEFT JOIN (SELECT TOP 1 * FROM dbo.tab1 ) AS sub1 ON 1=1 -- get single row
LEFT JOIN (SELECT TOP 1 * FROM dbo.tab2 ) AS sub2 ON 1=1
LEFT JOIN (SELECT TOP 1 * FROM dbo.tabC ) AS sub3 ON 1=1
Please treat it as starting point. You could easily extend it with WHERE condition for each subquery and return specific columns instead of *.
EDIT:
Version with UNION ALL:
DECLARE #sql NVARCHAR(MAX);
SELECT #sql = COALESCE(#sql + ' UNION ALL', '') +
FORMATMESSAGE(' SELECT TOP 1 tab_name=''%s'',col_name=''%s'',col_val=%s FROM %s'+CHAR(10)
,table_name, column_name, column_name, table_schema + '.' + table_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name LIKE 'colV%';
PRINT #sql;
EXEC(#sql);
DBFiddle Demo2

Get first row in table while printing out Table name and Column name

I need to get a quick overlook of the data in a MS SQL datase and found the following code which gives me all but the last column I need. This third column should show data from the first row.
SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
So my question is how I should formulate the SQL query to get a third column with data from the first row)?
//Update
This code gives me all I want except what table the data comes from. (In a similar question answered by Yaroslav at Select the first 3 rows of each table in a database)
DECLARE #sql VARCHAR(MAX)='';
SELECT #sql=#sql+'SELECT TOP 3 * FROM '+'['+SCHEMA_NAME(schema_id)+'].['+name+']'+';'
FROM sys.tables
EXEC(#sql)
One approach, if I get this correctly, was an undocumented stored procedure sp_MsForeachTable. The questionmark is a placeholder for the table's name there:
Hint: edit "YourDataBase"...
EXEC sp_msforeachtable 'USE YourDataBase;SELECT TOP 1 ''?'' AS TableName, * FROM ?';
With this query you can explore all first rows easily
CREATE TABLE #test(TableName NVARCHAR(MAX),Content XML)
EXEC sp_msforeachtable
'USE YourDataBase;INSERT INTO #test SELECT ''?'' AS TableName, (SELECT TOP 1 * FROM ? FOR XML PATH(''row''))';
SELECT * FROM #test;
UPDATE
Your own code would return the table's name also. Try this
DECLARE #sql VARCHAR(MAX)='';
SELECT #sql=#sql+'SELECT TOP 3 ''' + t.[name] + ''' AS TableName, * FROM '+'['+SCHEMA_NAME(schema_id)+'].['+name+']'+';'
FROM sys.tables t
EXEC(#sql)
I know this isnt much but it build you a select statement, you can then loop through each statement exec each statement or write a union, But I guess it could be a good starting point
Edit: You could also write a loop and exec each statement in a loop insert the value into a final table, Then just select from that table and you should be good.
SELECT
t.String
,t.q
,t.TABLE_NAME
,t.q2
,t.tbname
,t.com2
,t.q4
,t.COLUMN_NAME
,t.q5
,t.Columnname
,t.com3
,t.ColName
,t.[From]
,t.FromSelect
FROM (SELECT
'Select top 1 ' AS String
,'''' q
,TABLE_NAME
,'''' q2
,'as TableName'
as tbname
,',' com2
,'''' q4
,COLUMN_NAME
,'''' q5
,'as COLUMN_NAME'
as Columnname
,',' com3
,COLUMN_NAME as ColName
, 'Value From ' as [From]
,TABLE_NAME as FromSelect
,ROW_NUMBER() OVER (PARTITION BY TABLE_NAME ORDER BY TABLE_NAME DESC, COLUMN_NAME) rn
FROM INFORMATION_SCHEMA.COLUMNS c
) t
WHERE rn = 1;
The result will be something like this for each table.
Select top 1 ' zipcodes ' as TableName , ' CITY ' as COLUMN_NAME , CITY Value From zipcodes
Select top 1 ' _BHCAMERAPRICE ' as TableName , ' _BHID ' as COLUMN_NAME , _BHID Value From _BHCAMERAPRICE

Resources