More than Like Statement in a variable - sql

why this work :
SELECT * FROM Companies WHERE CompanyCode LIKE '%' AND BusinessUnitShortName LIKE 'CO%'
while mean this not work :
DECLARE #WHERECondition NVARCHAR(200) = ''
SET #WHERECondition = '''%'' AND BusinessUnitShortName LIKE ''CO%'''
SELECT * FROM Companies WHERE CompanyCode LIKE #WHERECondition
SELECT #WHERECondition

To make that work you need to use the dynamic sql like
DECLARE #WHERECondition NVARCHAR(200) = ''
SET #WHERECondition = '''%'' AND BusinessUnitShortName LIKE ''CO%'''
declare #sql nvarchar(Max)
Set #sql='SELECT * FROM Companies WHERE CompanyCode LIKE'+#WHERECondition
exec sp_executesql #sql
If you are not using the dynamic sql then you need to provide the column names as the SQL parser will look for the columns at the time when it is parsing the query and if not found will result in error.

You'd need to use dynamic SQL to achieve what you want. Your current method gets evaluated to something like this:
SELECT *
FROM Companies
WHERE CompanyCode LIKE '''%'' AND BusinessUnitShortName LIKE ''CO%'''
What you actually want is more like this:
DECLARE #sql NVARCHAR(MAX) = ''
DECLARE #WHERECondition = '''%'' AND BusinessUnitShortName LIKE ''CO%'''
SET #sql = 'SELECT * FROM Companies WHERE CompanyCode LIKE ' + #WHERECondition
EXEC(#sql);
which would evalute to:
SELECT * FROM Companies WHERE CompanyCode LIKE '%' AND BusinessUnitShortName LIKE 'CO%'

Related

Like in dynamic function

The code below works well. I however have issues trying to turn it into a like statement that I need some assistance with
CREATE PROCEDURE [dbo].[searcher]
#deliverer nvarchar (100)
AS
BEGIN
DECLARE #sql nvarchar(1000)
SET #sql = 'SELECT location, deliverer, charger FROM Store where 1=1'
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer =#pt'
DECLARE #t1 as TABLE
(
location varchar(1000),
deliverer varchar(100),
charger varchar(100)
)
INSERT INTO t1
EXEC sp_executesql #sql,
N'#pt nvarchar(100)',
#pt=location
SELECT * FROM t1
END
So far, I have tried the code below but with not much success
DECLARE #pt nvarchar (100)
SET #pt = '%' + #pt + '%'
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer like #pt'
I have also tried;
DECLARE #pt nvarchar (100)
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer like ''% + #pt + %'''
If your stored procedure parameter is #deliverer and your dynamic SQL parameter is #pt, I believe your sp_executesql execution should assign the parameter as #pt = #deliverer.
As for adding wildcards, you can either add them before the call with
SET #deliverer = '%' + #deliverer + '%'
or add them in the dynamic SQL with
SET #sql = #sql + ' and deliverer like ''%'' + #pt + ''%'''
Note the doubled up quotes around the %. The variable #pt is not quoted

is there a way to point at a specific column in a table through DECLARE in the WHERE clause?

I'm trying to create a searchstring that is a bit dynamic, and i'm trying to work around a large CASE WHEN scenario, but before i resort to doing a CASE WHEN i'm trying my luck here.
I've tried to execute it in string format "exec('code')" where it works, but then i get another issue with getdate() that i wont go into details with.
DECLARE #ProductLines nvarchar(50) = 'usr_author'
DECLARE #searchProductlines nvarchar(50) = 'hc'
SELECT TOP 20
Productid as Produktid,
usr_Author AS Author,
Header AS Title,
usr_Publisher AS Publisher,
CustomerId AS Customerid, FROM Products
WHERE
(#ProductLines Like '%' + #searchProductlines + '%')
I've scraped away all other code that isn't relevant here. What i want to do is declare #ProductLines as the column 'usr_author' so i in the WHERE clause can use #ProductLines as an dynamic column picker in a drop down menu later.
however, this doesnt work. if i write usr_Author instead of #ProductLines, i get the results i need but then it's a static solution, rather than a dynamic solution. what is best practice in this situation?
You can only replace constant values using parameters. You cannot replace identifiers -- including column names, table names, and so on.
You can do this dynamically as:
DECLARE #col nvarchar(50) = 'usr_author'
DECLARE #search nvarchar(50) = 'hc'
DECLARE #sql NVARCHAR(MAX);
SET #sql = '
SELECT TOP 20
Productid as Produktid,
usr_Author AS Author,
Header AS Title,
usr_Publisher AS Publisher,
CustomerId AS Customerid
FROM Products
WHERE #col Like ''%'' + #search + ''%''
';
SET #sql = REPLACE(#sql, '#col', #col);
EXEC sp_executesql #sql,
N'#search nvarchar(50)',
#search=#search;
By declaring this string, you're now comparing it as a string, not a column. Try a more dynamic SQL approach:
DECLARE #ProductLines nvarchar(50) = 'usr_author'
DECLARE #searchProductlines nvarchar(50) = 'hc'
DECLARE #sql1 nvarchar(500);
select #sql1 = 'SELECT TOP 20 Productid as Produktid, usr_Author AS Author, Header AS Title, usr_Publisher AS Publisher, CustomerId AS Customerid into #temptab1 FROM Products WHERE (' + #ProductLines + 'Like ''%' + #searchProductlines + '%'')'
exec( #sql1 )
select *
from #temptab1
Disclaimer: Not injection proof in the slightest, just a concept
create procedure dbo.uspSearch(
#searchProductId int = 0,
#searchAuthor nvarchar(50) = '',
#searchHeader nvarchar(50) = '',
#searchPublisher nvarchar(50) = '',
#searchCustomerId int = 0
) as
begin
set nocount on;
select top 20
Productid as Produktid,
usr_Author AS Author,
Header AS Title,
usr_Publisher AS Publisher,
CustomerId AS Customerid
from Products
where Productid = case when #searchProductId > 0 then #searchProductId else Productid end
and usr_Author like case when #searchAuthor <> '' then '%' + #searchAuthor + '%' else usr_Author end
and Header like case when #searchHeader <> '' then '%' + #searchHeader + '%' else Header end
and usr_Publisher like case when #searchPublisher <> '' then '%' + #searchPublisher + '%' else usr_Publisher end
and CustomerId = case when #searchCustomerId > 0 then #searchCustomerId else CustomerId end;
end;
go;
declare #searchProductId int = '1'
declare #searchAuthor nvarchar(50) = 'hc'
declare #searchHeader nvarchar(50) = 'test'
declare #searchPublisher nvarchar(50) = 'test'
declare #searchCustomerId int = '1';
exec dbo.uspSearch #searchProductId, #searchAuthor, #searchHeader, #searchPublisher, #searchCustomerId;
Besides the fact, that the whole approach has a certain smell, the best answer will be: Use dynamically created SQL (if you really have / want to stick to this). There are answers already...
Just for fun, there is a fully generic approach using XML like here:
I want to use a statement like this:
SELECT *
FROM sys.objects
WHERE [name]='sysrowsets';
...With generically defined parameters
DECLARE #ColumnName VARCHAR(100)='name';
DECLARE #SearchValue VARCHAR(100)='sysrowsets';
SELECT
(
SELECT *
FROM sys.objects
FOR XML PATH('o'),TYPE
).query('/*[*[local-name()=sql:variable("#ColumnName") and text()[1]=sql:variable("#SearchValue")]]')
The result is the same row as above, but as XML (which can be transformed into a tabular set again).
<o>
<name>sysrowsets</name>
<object_id>5</object_id>
<schema_id>4</schema_id>
<parent_object_id>0</parent_object_id>
<type>S </type>
<type_desc>SYSTEM_TABLE</type_desc>
<create_date>2012-09-02T23:08:12.370</create_date>
<modify_date>2012-09-02T23:08:15.340</modify_date>
<is_ms_shipped>1</is_ms_shipped>
<is_published>0</is_published>
<is_schema_published>0</is_schema_published>
</o>
As mentioned above, this is not the recommended approach, it will be very slow. I just felt the need to say something against the impossible statements :-)
UPDATE: Tabular result and still generic...
You can use something like this, just to articulate a predicate against a unique value (in this case object_id)
SELECT o.*
FROM sys.objects o
WHERE o.object_id=
(
SELECT *
FROM sys.objects
FOR XML PATH('o'),TYPE
).query('/*[*[local-name()=sql:variable("#ColumnName")
and text()[1]=sql:variable("#SearchValue")]]')
.value('(/o/object_id/text())[1]','bigint');

Why does the informationschema bring back malformed resuts with a like operator?

im having trouble with the below script:-
USE master
DECLARE #COMPANY CHAR(3)
declare #createdatabase char(50)
declare #fromdatabase char (50)
declare #sql1 char(100)
declare #logicaldatabasename Char(100)
declare #logicaldatabaselog char (100)
set #fromdatabase = 'a'
set #createdatabase = 'b'
SET #COMPANY = 'PUK'
;with q as (
SELECT [name] [logical_name]
FROM sys.[master_files]
WHERE [database_id] = DB_ID(#fromdatabase))
select #logicaldatabasename = q.[logical_name]
from q
where q.[logical_name] not like '%log%'
;with q as (
SELECT [name] [logical_name]
FROM sys.[master_files]
WHERE [database_id] = DB_ID(#fromdatabase))
select #logicaldatabaselog = q.[logical_name]
from q
where q.[logical_name] like '%log%'
select #logicaldatabasename AS LOGICALDATABASENAME, #logicaldatabaselog AS LOGICALDATABSELOG
--BACKUP DATABASE #fromdatabase
--TO DISK = '\folder\'+#fromdatabase+'.bak'
Set #sql1 = 'CREATE DATABASE '+#createdatabase
Exec (#sql1)
RESTORE DATABASE #createdatabase FROM DISK = '\flder\DANTEST.bak'
WITH MOVE #logicaldatabasename TO 'folder\b.mdf',
MOVE #logicaldatabaselog TO '\folder\b_log.ldf',
REPLACE
select * from sys.master_files where database_id = db_id(#createdatabase)
;
go
use b
go
;
DECLARE cCursor CURSOR LOCAL FAST_FORWARD FOR
#NAME?
SELECT
IST.TABLE_NAME AS tblName
FROM
nhba_a.INFORMATION_SCHEMA.TABLES IST
WHERE RIGHT(IST.TABLE_NAME,3) <> 'PUK' AND IST.TABLE_TYPE = 'BASE TABLE' and ist.TABLE_NAME like '%_%'
ORDER BY IST.TABLE_NAME
--
DECLARE #tblName VARCHAR(255)
--
DECLARE #sql NVARCHAR(4000)
DECLARE #crlf CHAR(2)
SET #crlf = CHAR(13) + CHAR(10)
OPEN cCursor
FETCH cCursor
INTO #tblName
WHILE ##fetch_status = 0
BEGIN
if #tblname like '%_%'
SET #sql = 'DROP TABLE '+QUOTENAME(#tblName);
EXEC sp_executesql #sql;
FETCH cCursor
INTO #tblName
END
when using this:-
SELECT
IST.TABLE_NAME AS tblName
FROM
nhba_a.INFORMATION_SCHEMA.TABLES IST
WHERE RIGHT(IST.TABLE_NAME,3) <> 'PUK' AND IST.TABLE_TYPE = 'BASE TABLE' and ist.TABLE_NAME like '%_%'
ORDER BY IST.TABLE_NAME
I get tables without a _ but I have searched for tables with only _.
could anyone explain why its not coming back with the correct results and what sql is actually doing in the background?
I have tried varies ways to bring up the correct results but have not able to find out what the problem is because the logic is sound.
When you are using LIKE operator the underscore _ actually referees to any ONE character. It means _ has a special meaning with the LIKE operator.
If you want to return table names where there is an underscore then you need to escape the underscore in your where clause, something like...
WHERE TABLE_NAME like '%\_%' ESCAPE '\'
Or you can also use the square brackets to escape the underscore without using the keyword ESCAPE
WHERE TABLE_NAME like '%[_]%'

Queries using LIKE wildcards in sql server

I want to perform a small SQL server search in my ASP.NET web project. My database is not big so I think it's better not to use full-text-search.
I want to perform a simple search like this:
select * from mytable where columnA LIKE '%something%'
I can use = in the following way:
select * from mytable where columnA='"+myVariable+"'
but how can I use a variable instead of %something% in the LIKE phrase?
Is this correct:
LIKE '"+%myVariable%+"'?
Use:
where columnA LIKE '%' + myVariable + '%'
WHERE
columnName LIKE '%' + myVarCharVariable +'%'
Try this query:
select * from tablename where colname like '%' + #varname + '%'
Hope it helps.
I just tried this and found you can do as below:
SELECT * FROM whatever WHERE column LIKE '%'+#var+'%'
DECLARE #myVariable varchar(MAX)
SET #myVariable = 'WhatYouAreLookingFor'
SELECT * FROM mytable
WHERE columnA LIKE '%' + #myVariable + '%'
In case someone else stumbles into this post like I did. On SSMS 2012 with a SQL 2012 Server back end I was able to use code as follows without issues.
Declare #MyVariable
Set #MyVariable = '%DesiredString%'
Select *
From Table_A
Where Field_A like #MyVariable
Then each time you want to change the Desired String just change it at the Set statement.
I know this post was made prior to 2012 that is why I am mentioning it in case someone with a newer setup looks up this post.
Well you could do something like:
var query = "SELECT * FROM MyTable WHERE columnA LIKE '%" + myVariable + "%'";
If you are worried about sql injection, try something like this instead. It's more complex, but it works and should satisfy security requirements. Let's say someone passed a value into your stored procedure using a parameter called "#searchstring".
DECLARE #searchString nvarchar(100) = 'test',
#SQL nvarchar(max),
#foundSearchHit bit,
#paramdef nvarchar(max) = '#foundSearchHit bit OUTPUT'
SET #searchstring = '%' + #searchString + '%'
SET #SQL = '
SELECT TOP 1 #foundSearchHit = 1
FROM sys.databases WHERE [name] like ' +
QUOTENAME(#searchString,'''')
EXEC sp_executeSQL #SQL, #paramdef, #foundSearchHit = #foundSearchHit OUTPUT
SELECT #foundSearchHit
That should do the trick.

In storprocedure how to set variable on where?

CREATE PROCEDURE[BoardID]
#sParent varchar(8000)
AS
Select Boardid,PONO,ImageStatus
from BoardDetail
Where
Boardid=1 and #sParent
Why #sParent create error how to use this variable on where ......i want to supply string as parameter and it will be set on where ......like #sParent
It sounds like what you really want is to create a dynamic sql statement if that's what you want then try this:
Create Procedure [BoardID]
#sParent varchar(8000)
AS
Declare #SQL VarChar(8500)
SELECT #SQL = 'Select Boardid,PONO,ImageStatus from BoardDetail Where
Boardid=1 and '
SELECT #SQL = #SQL + #sParent
Exec ( #SQL)
GO
You need to set a field to your #sParent parameter in the WHERE clause:
...
WHERE
Boardid = 1 AND [fieldNameThatIsMatchingSParent] = #sParent
...
or similar.
If you want to pass where clause into your sp try this :
CREATE PROCEDURE[BoardID]
#sParent varchar(8000)
AS
DECLARE #sql ntext
SET #sql = 'Select Boardid,PONO,ImageStatus from BoardDetail Where Boardid=1'
IF (#sParent <> '')
BEGIN
SET #sql = #sql + ' and ' + #sParent
END
EXEC #sql
WHERE
((#Boardid is null and 1=1)
OR
(#Boardid is not null and #Boardid = SomeTbl.Boardid))
This WHERE clause allows us to have an optional SQL Parameter without having to resort to dynamically constructed SQL.
Hope that helps!
You can use #sParent in where in 2 ways (depending what you need)
where [FieldName] = #sParent
or
where [FieldName] Like #sParent
CREATE PROCEDURE[BoardID]
#sParent VARCHAR(8000)
AS
SELECT Boardid, PONO, ImageStatus
FROM BoardDetail
WHERE
Boardid = 1
AND ('0' != #sParent AND [ColumnName] LIKE #sParent)