Syntax issue when using dynamic query - tsql

Query 1:
SET #sql2 = 'insert into TempReport
select ID, max(TransactionTime),0 from ClubTransaction with (nolock)
where ClubcardID in (select ClubcardID from TempCC)
and ClubcardTransaction.OfferID not in (119,120,121)
group by ClubcardID'
exec (#Sql2)
Query 2:
delcare #OfferID varchar(50)
set OfferID='1,112,445,'
SET #sql2 = 'insert into TempReport
select ID, max(TransactionTime),0 from ClubTransaction with (nolock)
where ClubcardID in (select ClubcardID from TempCC)
and ClubcardTransaction.OfferID not in (Select Item From dbo.fnSplit(#OfferID,'','')
group by ClubcardID'
exec (#Sql2)
Query 1 works fine. In query2 I am replacing with an variable de defined where I am passing to the function fnSplit where I split the values with comma separated.
I get an error message Must declare the scalar variable "#OfferID".
Please let me know where is the issue here.

You have to put the value from outside and replace the ' by ":
Query 2:
declare #OfferID varchar(50)
set OfferID='1,112,445,'
SET #sql2 = 'insert into TempReport
select ID, max(TransactionTime),0 from ClubTransaction with (nolock)
where ClubcardID in (select ClubcardID from TempCC)
and ClubcardTransaction.OfferID not in (Select Item From dbo.fnSplit(' + replace(convert(varchar(4000), #OfferID), '''', '''''') + ',"","")
group by ClubcardID'
exec (#Sql2)
Another solution (and a better one) is to use sp_executesql
Be aware that dynamic SQL is a way to make sql injections and you should avoid using it..

Related

Execute result of a PostgreSQL query again to get the final result set?

I'm looking for a way to get the list of all json attributes across all my PostgreSQL tables dynamically.
I have Query 1 which would generate a list of sql statements, and then run that sql statements to get the final output all in one go (like the dynamic SQL concept in SQL server).
Query 1 looks like this :
create temporary table test (ordr int, field varchar(1000));
-- Step 1 Create temp table to insert all table/col/json attrbute info
insert into test(ordr,field)
select 0 ordr,'create temporary table temp_table
( table_schema varchar(200)
,table_name varchar(200)
,column_name varchar(200)
,json_attribute varchar(200)
,data_type varchar(50)
);'
union
-- Non json type columns
select 1 ordr, 'insert into temp_table(table_name, column_name,data_type,json_attribute)'
union
-- Json columns with data like json object
select
3 ordr,
concat('select distinct ''', t.table_name, ''' tbl, ''', c.column_name, ''' col, ''' , c.data_type,''' data_type, '
,'jsonb_object_keys(', c.column_name, ') json_attribute', ' from ', t.table_name,
' where jsonb_typeof(' , c.column_name, ') = ''object'' union') AS field
from information_schema.tables t
join information_schema.columns c on c.table_name = t.table_name
where t.table_schema not in ('information_schema', 'pg_catalog')
--and table_type = 'BASE TABLE'
and c.data_type ='jsonb';
--final sql statements to build temp table
--copy all the column "txt" to a separate window and execute it, it will create a temp table "temp_table" which will have all tables/cols/json attributes
select ordr
,(case when t.ordr = (select max(t2.ordr) from test t2) then replace(field,'union','') else field end) txt
from test t
union
select 9999, ';select * from temp_table;'
order by 1 ;
Query 1 output : This is a list of sql statements
I'm looking for a way to run the Query 1 & Query 1 output which would get me the final output all in one go.
Any lead or guidance will be really appreciated.

T-SQL find string with lowercase and uppercase

I have a database with several tables and I need to search every varchar column across the database, for columns that simultaneously contain lower and upper case characters.
To clarify:
If one column contains helLo the name of the column should be returned by the query, but if the column values only contain either hello or HELLO then the name of the column is not returned.
Let's exclude all UPPER and all LOWER, the rest will be MIXED.
SELECT someColumn
FROM someTable
WHERE someColumn <> UPPER(someColumn) AND someColumn <> LOWER(someColumn)
EDIT:
As suggested in comments and described in detail here I need to specify a case-sensitive collation.
SELECT someColumn
FROM someTable
WHERE someColumn <> UPPER(someColumn) AND
someColumn <> LOWER(someColumn)
Collate SQL_Latin1_General_CP1_CS_AS
It sounds like you are after a case sensitive search, so you'd need to use a case sensitive collation for there WHERE clause.
e.g. if your collation is currently SQL_Latin1_General_CP1_CI_AS which is case insensitive, you can write a case sensitive query using:
SELECT SomeColumn
FROM dbo.SomeTable
WHERE SomeField LIKE '%helLo%' COLLATE SQL_Latin1_General_CP1_CS_AS
Here, COLLATE SQL_Latin1_General_CP1_CS_AS tells it to use a case sensitive collation to perform the filtering.
I think I understand that you want to find any varchar column with mixed case data within it?
If so, you can achieve this with a cursor looking at your column types, which then executes some dynamic SQL on the varchar columns it finds to check the data for mixed case values.
I thoroughly recommend doing this on a non-production server using a copy of your database, not least because you need to create a table to deposit your findings into:
create table VarcharColumns (TableName nvarchar(max), ColumnName nvarchar(max))
declare #sql nvarchar(max)
declare my_cursor cursor local static read_only forward_only
for
select 'insert into VarcharColumns select t,c from(select ''' + s.name + '.' + tb.name + ''' t, ''' + c.name + ''' c from ' + s.name + '.' + tb.name + ' where ' + c.name + ' like ''%[abcdefghijklmnopqrstuvwxyz]%'' COLLATE SQL_Latin1_General_CP1_CS_AS and ' + c.name + ' like ''%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%'' COLLATE SQL_Latin1_General_CP1_CS_AS having count(1) > 0) a' as s
from sys.columns c
inner join sys.types t
on(c.system_type_id = t.system_type_id
and t.name = 'varchar'
)
inner join sys.tables tb
on(c.object_id = tb.object_id)
inner join sys.schemas s
on(tb.schema_id = s.schema_id)
open my_cursor
fetch next from my_cursor into #sql
while ##fetch_status = 0
begin
print #sql
exec(#sql)
fetch next from my_cursor into #sql
end
close my_cursor
deallocate my_cursor
select * from VarcharColumns
You can check the hash compared to its upper and lower values... here is a simple test:
declare #test varchar(256)
set #test = 'MIX' -- Try changing this to a mix case, and then all lower case
select case
when hashbytes('SHA1',#test) <> hashbytes('SHA1',upper(#test)) and hashbytes('SHA1',#test) <> hashbytes('SHA1',lower(#test))
then 'MixedCase'
else 'Not Mixed Case'
end
So using this in a table... you can do something like this
create table #tempT (SomeColumn varchar(256))
insert into #tempT (SomeColumn) values ('some thing lower'),('SOME THING UPPER'),('Some Thing Mixed')
SELECT SomeColumn
FROM #tempT
WHERE 1 = case
when hashbytes('SHA1',SomeColumn) <> hashbytes('SHA1',upper(SomeColumn)) and hashbytes('SHA1',SomeColumn) <> hashbytes('SHA1',lower(SomeColumn)) then 1
else 0
end

Conversion failed when converting the varchar value '1, 2, 3' to data type int

I can't seem to find a solution to this problem. Following is my query:
Declare #MY_STUDENT_ID Varchar(100)
Select #MY_STUDENT_ID = COALESCE(#MY_STUDENT_ID + ',', '') + Convert(varchar, STUDENT_ID) From Some_TABLE Where FISCAL_YEAR = '2014'
SELECT * FROM Table_Students WHERE STUDENT_ID IN (#MY_STUDENT_ID)
Basically first query runs and give me all student IDs as a string concatenated with , for e.g. 1,2,3
And then this value is passed into second query but second query is giving this error which I have posted in title. No idea what to do so any help will be appreciated.
Type of STUDENT_ID field is int.
There is absolutely no need to mess about with comma delimited lists here.
Just use the sub query directly
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN (SELECT StudentId
From Some_TABLE Where FISCAL_YEAR = '2014')
Your approach does not work as it ends up generating something with semantics of
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN ('1,2,3')
Which is not the same as
SELECT *
FROM Table_Students
WHERE STUDENT_ID IN (1,2,3)
As it just is a single string parameter with contents that happen to resemble an in list, rather than 3 int parameters.
You could do so using dynamic SQL, but in this scenario, Martin SMith's answer seems to be better. Should you, however, wish to use dynamic SQL, this would be the way to do so (untested pseudo-code):
Declare #MY_STUDENT_ID varchar(100);
DECLARE #sql nvasrchar(max);
Select #MY_STUDENT_ID = COALESCE(#MY_STUDENT_ID + ',', '') + Convert(varchar, STUDENT_ID) From Some_TABLE Where FISCAL_YEAR = '2014'
SELECT #sql = 'SELECT * FROM Table_Students WHERE STUDENT_ID IN (' + #MY_STUDENT_ID + ')';
EXEC sp_executesql #sql;

Syntax error in sybase iq dynamic query

I am new to Sybase IQ and when I try to execute this code, an error is displayed
Could not execute the statement. Syntax error near SELECT on line 1
DECLARE #SQL VARCHAR(500)
SET #SQL='SELECT * FROM SNP_CHECK_TAB A INNER JOIN SELECT * FROM E$_auditemp_trg B ON B.ODI_ORIGIN = A.ORIGIN WHERE B.ODI_SESS_NO =532001 ORDER BY B.ODI_CHECK_DATE DESC'
EXECUTE(#SQL)
Please help me fix this.
Thanks in advance
You have missed parenthesis around second query for Inner Join.
You Have to use like
... INNER JOIN (SELECT * FROM E$_auditemp_trg ) B ...
-- ^ you need to enclose here
Instaed of
INNER JOIN (SELECT * FROM E$_auditemp_trg B ON B.ODI_ORIGIN = A.ORIGIN WHERE
B.ODI_SESS_NO =532001 ORDER BY B.ODI_CHECK_DATE DESC)
-- ^ (not here)
Try like this
DECLARE #SQL VARCHAR(500)
SET #SQL='SELECT * FROM SNP_CHECK_TAB A INNER JOIN (SELECT * FROM E$_auditemp_trg) B ON B.ODI_ORIGIN = A.ORIGIN WHERE B.ODI_SESS_NO =532001 ORDER BY B.ODI_CHECK_DATE DESC'
EXECUTE(#SQL)

Iterate through result-sets in T-SQL

I would like to write a stored procedure using a statement to iterate through a result-set of records provided by another statement, and union the end results into one single result-set. Can anyone advise on an approach for this?
For example, a generic set of records to iterate through:
SELECT sys.schemas.name + '.' + sys.objects.name as [schm_obj]
FROM sys.objects
INNER JOIN sys.schemas
ON sys.objects.schema_id = sys.schemas.schema_id
AND sys.schemas.name IN ('dbo')
Generic query to be executed on each record:
SELECT DISTINCT referenced_schema_name + '.' + referenced_entity_name
FROM sys.dm_sql_referenced_entities(#schm_obj,'OBJECT')
The parameter #schm_obj to be replaced by a single field value returned in each row of the first query; eventually, I would like to union all results. Any advice would be greatly appreciated.
You need to do dyanmic sql to do this. I am confused as you are stating a procedure then showing a table function. Table Functions unless something changed in 2012 cannot do dynamic sql. If you want to basically create a programmable object you can use to get data that YOU SUPPLY the schema or meta detail to get to it I would use a dynamic procedure that would label what you got and then give you the value of it. Then you could insert this into a table variable and iterate or insert into it till your heart's content.
create proc dbo.Dynaminizer
(
#ObjName nvarchar(64)
)
as
BEGIN
declare #SQL nvarchar(1024)
Select #SQL = 'Select ''' + #ObjName + ''' as Name, ' + #ObjName + ' from sys.tables'
EXECUTE sp_executesql #SQL
END
declare #temp table ( name varchar(32), value varchar(128))
insert into #Temp
exec Dynaminizer 'name'
insert into #Temp
exec Dynaminizer 'object_id'
select *
from #Temp
UPDATE LATER THAT DAY....
If you just want to take values from one table or set and then perform operations in a function that takes a schema and a name combo then there is another method to do that. I would use a cte to make a custom column and then do a cross apply to perform that dataset in a function for how many rows that are in the set. This will evaluate your function like it was executing it for each value and then posting the results. There is no need to union unless you are more specific for what you are wanting to do. You can take it even further and if you want the dependencies inline(as opposed to seperate rows) you can relate the dataset back to itself and then do an xml type to cast out the dependencies into a comma seperated list.
Example usage of both:
-- multi row example to show referencing relationships
with procs as
(
Select
schema_name(schema_id) + '.' + name as Name
from sys.procedures p
)
select
p.Name
, referenced_schema_name + '.' + referenced_entity_name as Ref
from procs p
cross apply sys.dm_sql_referenced_entities(p.Name,'OBJECT')
;
-- take it a step further and put relationships inside a single column
with procs as
(
Select
schema_name(schema_id) + '.' + name as Name
from sys.procedures p
)
, setup as
(
select
p.Name
, referenced_schema_name + '.' + referenced_entity_name as Ref
from procs p
cross apply sys.dm_sql_referenced_entities(p.Name,'OBJECT')
)
Select distinct
Name
, stuff(
(
select
', ' + Ref
from setup x
where x.Name = m.Name
for xml path('')
)
, 1, 2, '') as Dependencies
from setup m