Incorrect syntax near '%'. inside dynamic SQL - sql

I just found out about dynamic SQL but when I add a wildcard like '%', I get this error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '%'.
Here is the query:
declare #Filter varchar(50)
set #Filter = '2%'
exec ('select * from dbo.tbl_coa where acct_code like ' + #Filter)
Anyway to fix this or is it impossible with dynamic SQL?

You need to enclose #Filter in quotes:
exec ('select * from dbo.tbl_coa where acct_code like ''' + #Filter + '''')
Demo on SQLFiddle
Note it is better to put the needed quotes into the query that you execute so that if you do something like
set #Filter = (SELECT ... )
The query will still work without having to do something like
set #Filter = concat('''', (select '2%'), '''')

You are concating the string incorrectly.
You should fix it to set #Filter = '''2%''', check the result below.
Demo on db<>fiddle
declare #Filter varchar(50)
set #Filter = '''2%'''
print ('select * from dbo.tbl_coa where acct_code like ' + #Filter)
// Output: select * from dbo.tbl_coa where acct_code like '2%'
Full Demo on db<>fiddle
create table tbl_coa(
acct_code varchar(10)
)
insert into tbl_coa
values('21'),('20'),('30')
declare #Filter varchar(50)
set #Filter = '''2%'''
exec ('select * from dbo.tbl_coa where acct_code like ' + #Filter)
Output
acct_code
21
20

Related

Use subquery after AS alias

I am trying to use subquery after alias AS in SQL server 2019, here is my sql query:
select concat(sum(labst),' kg') as (select distinct name1 from mb52 where werks='1202') from mb52 where werks='1202';
but this query giving this error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '('.
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'from'.
I want to get the result like this:
1202
--------------------------------------------
343979.535 kg
instead of using select concat(sum(labst),' kg') as "1202",
because I get the value of werks from a variable $werks and my final SQL query look like this:
select concat(sum(labst),' kg') as (select distinct name1 from mb52 where werks in ($werks)) from mb52 where werks in ($werks);
Can anyone help me on this problem,please?
You can use dynamic sql like this
declare #sql varchar(1000)
declare #name varchar(100)
declare #werks varchar(1000) = '1202, 1200'
select distinct
#name = name1
from mb52
where werks = 1202
set #sql = 'select concat(sum(labst), '' kg'') as ''' + #name + ''' from mb52 where werks in (' + #werks + ')'
exec (#sql)
See this DBFiddle where you can try it yourself
However, there is a major problem with your query, as you write
as (select distinct name1 from mb52 where werks in ($werks))
This can return more than one value for name1 if there are more then one value in $werks
So I changed it to = 1202 like the other answer also did
Your query probably needs to more like this
set #sql2 = 'select concat(sum(labst), '' kg'') as ''' + #name + ''' from mb52 where werks = 1202'
where again I changed the in $werks into = 1202 because I think it will produce wrong results, but that is up to you.
Look at the dbfiddle and play with it until it does what you need.
EDIT
As requested in the comments, here is how the query looks like with just one value in $werks
set #sql2 = 'select concat(sum(labst), '' kg'') as ''' + #name + ''' from mb52 where werks = ' + #werks
The DBFiddle is also altered
you should use dynamic sql to get this working
DECLARE #S NVARCHAR(MAX)
SELECT distinct #S = 'select concat(sum(labst),'' kg'') as '+ name1 +' from mb52 where werks=''1202''' from mb52 where werks='1202'
EXEC (#S)
To do this, you need to use a dynamic query
like this:
DECLARE #query NVARCHAR(MAX) = 'select concat(sum(t1.labst),'' kg'') as '+ (SELECT DISTINCT
t1.name1 FROM dbo.mb52 t1 WHERE t1.werks = '1202') + ' from dbo.mb52 t1 where t1.werks=''1202'''
EXEC sp_executesql #query

SQL all fields with com # (SELECT * FROM)

I need run a generic SQL query with the character # between each field in the query result so that I can work with in Excel. I.E:
SELECT * FROM EMPLOYEE
RESULT
NAME#AGE#SALARY#EMAIL
Bob#59#1700#bob#bob.com
How can I to do this?
In Caché you can export data with System Management Portal. You can read how you can do it in the documentation.
SELECT Name + '#' + AGE FROM Employee
Or you may need to convert some fields, in MSSQL it looks like:
SELECT (CONVERT(VARCHAR(255), E.Age) + '#')
FROM Employee E
If you cannot specify values:
DECLARE #tableName VARCHAR(255) = 'Employee'
-- use MAX since this will be a long query
DECLARE #csv VARCHAR(MAX)
-- Create a query containing SELECT CONVERT(varchar(255), COALESCE(columnanme, '')) for all column names, in 1 line
-- COALACE in case a column is null (otherwise result will be 'null'.
SELECT #csv = COALESCE(#csv + 'CONVERT(VARCHAR(255),COALESCE(' + SC.name + ', '''')) + ''#'' + ', '')
FROM sysobjects SO
JOIN syscolumns SC ON SC.id = SO.id
WHERE SO.name = #tableName
-- chop off the last ','
SET #csv = (SELECT LEFT(#csv, LEN(#csv) -1))
SET #csv = 'SELECT ' + #csv + ' FROM ' + #tableName
-- for debugging:
-- SELECT #csv
-- execute the SQL query
EXEC #csv
Edit for MSSQL, 'EXEC' will truncate the #csv variable, if this is the case you'll have to use 2 variables (or more if #csv is longer than 2000)
DECLARE #csvPartOne VARCHAR(500) = LEFT(#csv, 500)
DECLARE #csvPartTwo VARCHAR(MAX) = RIGHT(#csv, LEN(#csv) - 500)
-- execute the SQL query
EXEC (#csvPartOne + #csvPartTwo)

Why my sqlserver procedure cannot output %

I have a sql statement below but it does not work. The error msg is "Incorrect syntax near the keyword 'AS'.". I found when I remove '%', it works as it should but I need to output '%' in this sql, can someone provide me with some suggestions?
declare #per varchar(10) = '0.00%'
set #str = 'select ' + #per + ' AS ColumnA from #TempSui' ;
exec (#str)
What you execute is:
select 0.00% AS ColumnA from #TempSui', you need to add quotes:
'select ' + QUOTENAME(#per, '''') + ' AS ColumnA from #TempSui'
I think you just miss the quotes
declare #per varchar(10) = '0.00%'
set #str = 'select ''' + #per + ''' AS ColumnA from #TempSui' ;
exec (#str)
It is not a bad idea to use PRINT when you debug a dynamic TSQL:
print #str
Will give :
select '0.00%' AS ColumnA from #TempSui
Learn to use parameters. Then you wont' have this problem:
declare #per varchar(10) = '0.00%'
set #str = 'select #per AS ColumnA from #TempSui' ;
exec sp_executesql #str, N'#per varchar(10)', #per=#per;
Voila! No issues at all. And, your code is safer and might be more efficient too (no need to recompile every time it is run).

SQL results to string with wildcard

Suppose you have a table like this:
ID FNAME LNAME
1 Bob Smith
2 Sally Jones
A simple SELECT * FROM [Table] will return all rows. But what if you wanted to build a single string out of the results, and the column names are unknown? In other words, this will not work:
SELECT ID + ',' + FNAME + ',' + LNAME FROM [Table]
because you don't know the column names. Additionally, COALESCE won't work because it doesn't accept wildcards. Ideally you want to execute something like this:
SELECT dbo.FunctionThatSplitsResultsToString(*) FROM [Table]
and have it return
1,Bob,Smith
2,Sally,Jones
Is this possible?
This is a corrected version of the answer #Igor gave. In addition to concatenating comma characters between the values, it converts NULL values to an empty string (because concatenating a string to NULL results in a NULL value).
DECLARE #sql NVARCHAR(max)='SELECT '
DECLARE #TableName NVARCHAR(max) = 'Table_Name' -- <-- Set the target table name here
SELECT #sql=#sql+N'ISNULL(CAST(' + name +' as NVARCHAR(max)), '''')+'',''+'
FROM sys.columns
WHERE object_id=OBJECT_ID(#TableName)
SELECT #sql=SUBSTRING(#sql,1,LEN(#sql)-5)+N' FROM ' + #TableName
--SELECT #sql -- uncomment to see the query string
EXEC sp_executesql #sql
As the first Igor noted, the solution is dynamic SQL. You need to construct the underlying SQL statement correctly.
The following code casts all columns to varchar() and then concatenates them together. The final form of the SQL removes the last "+" sign and adds the from statement:
declare #sql varchar(max);
select #sql = (select 'cast('+coalesce(column_name, '') + ' as varchar(255)) +'
from information_schema.columns
where table_name = <whatever>
for xml path ('')
);
select #sql = left(#sql, len(#sql - 2)) + ' from t';
exec(#sql);
I admit to being US-centric and rarely using internationalization. The whole thing also works with nvarchars().
Try the below one
GO
DECLARE #ColumnsList VARCHAR(MAX), #SelectStatement VARCHAR(MAX),#TargetTable VARCHAR(250) ,#FINALSQL NVARCHAR(MAX)
SET #TARGETTABLE ='TempData'
SELECT #ColumnsList = COALESCE( #ColumnsList+' + '','' +' ,'') + 'Cast('+ A.COLUMN_NAME + ' AS Varchar(250))'
FROM (select Column_Name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME= #TARGETTABLE) A
SELECT #FinalSql = 'Select ' +#ColumnsList + ' FROM ' + #TARGETTABLE
EXEC SP_EXECUTESQL #FINALSQL
GO

SQL syntax error

Im using Microsoft SQL Server which I think is T-SQL or ANSI SQL.
I want to search a database with a string. The matches that fit the begging of the string should come first then sort alphabetically.
I.e. If the table contains FOO, BAR and RAP
a search for the string 'R' should yield:
RAP
BAR
In that order.
Here is my attempt:
SELECT Name
FROM MyTable
WHERE (Name LIKE '%' + #name + '%')
ORDER BY (IF(Name LIKE #name + '%',1,0))
The error message is: "must declare scalar variable #name"
declare #name varchar(10)
set #name='R'
SELECT Name
FROM (select 'foo' as name union select 'RAP' union select 'BAR') MyTable
WHERE (Name LIKE '%' + #name + '%')
ORDER BY charindex(#name ,name)
.
DECLARE #name VARCHAR(MAX);
SET #name = 'foo';
SELECT Name
FROM MyTable
WHERE Name LIKE '%' + #name + '%'
ORDER BY CASE WHEN Name LIKE #name + '%' THEN 1 ELSE 0 END;
Other solutions seem to miss the "sort alphabetically" part:
DECLARE #Search VARCHAR(MAX)
SET #Search = 'R'
SELECT 0, Name
FROM MyTable
WHERE Name LIKE #Search + '%'
UNION ALL
SELECT 1, Name
FROM MyTable
WHERE Name like '%_' + #Search + '%'
ORDER BY 1, 2
Seems that you missed variable declaration:
DECALRE #name varchar(50) -- adjust type and length of variable
SET #name = 'phrase' -- for MSSQL 2008 you can do it in one line