Build dynamic query according to variable value - sql

I am using SQL Server 2008 R2.
I am facing problem while fetching records from database in Role Based Access.
I have a Table let us say TableA. I have 5 Columns in it i.e, ID (primary key), FirstName, LastName, RegistrationNumber, EmployeeIdent.
All the columns except ID are of Varchar type.
I have a stored procedure to search the records. I am passing string to it and finding matching records from all five columns.
Now, the problem I am facing is in Role Based Access.
The requirement is when user is of "Admin" type then find matching records from all five columns but when is of "naive" user type then search matching records from only ID column.
I have passed the variable #userType to stored procedure from which I can determine the user type.
One way to resolve this problem is If Condition. Like if (#userType) = 'Admin' then some query Else Some other.
But I don't want to write query in If Condition.
Another way to resolve this is to store query in varchar type of variable and then execute is using EXEC (), but I have heard that it creates more overhead on server (I am not sure about it).
So any other way to fulfill this requirement?
The query to search records is
DECLARE #SearchText VARCHAR(MAX)= ''
SELECT *
FROM TableA
WHERE
Convert(varchar,ID) LIKE CASE WHEN LEN(#SearchText) = 0 THEN Convert(varchar,ID) ELSE '%'+ ISNULL(#SearchText,'0') + '%' END OR
FirstName LIKE CASE WHEN LEN(#SearchText) = 0 THEN FirstName ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
LastName LIKE CASE WHEN LEN(#SearchText) = 0 THEN LastName ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
RegistrationNumber LIKE CASE WHEN LEN(#SearchText) = 0 THEN RegistrationNumber ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
EmployeeIdent LIKE CASE WHEN LEN(#SearchText) = 0 THEN EmployeeIdent ELSE '%'+ ISNULL(#SearchText,'') + '%' END

SELECT
*
FROM TABLEA
WHERE
(#userType = 'admin'
--add any other criteria for admin type here
) or (
#userType = 'naive'
--add any other criteria for naive type here
)

Related

How to do a conditional where clause with where in PL/SQL within Procedure

I have a pretty simple Stored Procedure that I am in trouble to do because i'm new to SQL and PL/SQL. I Have a table with a name column that is a varchar(55).
I discovered that if the user executes my procedure with an empty string as a paramter the LIKE statment brings all rows from TABLE1
SELECT *
FROM TABLE1
WHERE COLUMN LIKE VARIABLE || '%'
AND...
So I tried to change the query so if the VARIABLE is passed with a empty string it can still perform other conditions in the where statment.
SELECT *
FROM TABLE1
WHERE (VARIABLE <> '' AND COLUMN LIKE VARIABLE || '%')
AND...
But now wherever I pass as variable ('', NULL, 'anystring') I get no rows returned.
How can I build a query that validates if the variable is different of empty string and if it is it performs the LIKE statment with the variable correctly?
If I understand you correctly, it is not difficult thing to do. You can use conditional WHERE clause using CASE WHEN. So your query will support different scenarios, something like this:
SELECT *
FROM TABLE1
WHERE (CASE WHEN variable IS NULL AND column IS NULL THEN 1
WHEN variable LIKE '%' AND column LIKE variable||'%' THEN 1
ELSE 0
END) = 1
AND...
Basically, it checks if the variable = '' then it will compare the column against ''. Otherwise, it will compare it against variable||'%'.
Notice, Oracle treats empty string of the type VARCHAR as NULL (this does not apply to CHAR). So, in the first scenario we compare against NULL.
Hello Just a thought for this we can use Dynamic sql too. If you may try this approach. Hope it helps.
CREATE OR REPLACE PROCEDURE SPS_TEST_OUT(
p_input_in IN VARCHAR2
)
AS
lv_sql LONG;
lv_where VARCHAR2(100);
BEGIN
lv_where:= CASE WHEN p_input_in IS NULL OR p_input_in = '' THEN
''
ELSE
' AND COLUMN1 LIKE '''||p_input_in||'''%'
END;
lv_sql:='SELECT * FROM TABLE
WHERE 1 = 1
' ||lv_where;
dbms_output.put_line(lv_sql);
END;

How to add multiple conditions in sql?

Here is my stored procedure:
ALTER PROCEDURE sp_searchedstudentrecords
(
#condition varchar(20),
#searchtext varchar(50),
#searchclass int
)
AS
begin
If (#condition = 'startswith')
select * from student where name like #searchtext+ '% '
else if (#condition = 'endswith')
select * from student where name like '%' +#searchtext
else
select * from student where name like '%' +#searchtext+ '%'
End
I have been added extra one text box for search by class with the above query.
#searchclass int
May i now what should be the query for search by class look like?
I'm new sql query and .net,
I have been created dropdown contains startswith,endswith and contains and one text box for search by name.
I already done select record where search by name, with this i need to select record from table where search by class.
Can anyone guide me for query?
Thanks,
Like this
select *
from student
where name like (case
when #condition = 'startswith' then #searchtext+ '% '
else
case when #condition = 'endswith' then '%' + #searchtext
else '%' + #searchtext + '%'
end
end)
and studentid = isnull(#searchclass, studentid)
Above query to studentid has been extra search
If any id to search passing value other wise pass null
This query should be given result.
As already suggested, it is better to do this in your front-end by constructing a parameterized query as described here. Since you cannot use the protective power of parameterized with LIKE, you must be careful to sanitize your string (avoid Sql injection).
When implementing in .NET, it is best practice to avoid string comparisons. You can define your filters as a fixed list of id->name pairs.
enum LikeFilterType
{
Startswith = 1,
Endswith = 2,
Inside = 3
// maybe exactly can be added later
}
IList<SelectListItem> FilterOptions = new List<SelectListItem>()
{
new SelectListItem() { Value = (int) LikeFilterType.Startswith, Text = "Starts with" },
new SelectListItem() { Value = (int) LikeFilterType.Endswith , Text = "Ends with" },
new SelectListItem() { Value = (int) LikeFilterType.Inside, Text = "Inside" }
}
Your combo may "bind" directly to this list and use selected value, not the string in your logic (what you display may change over time, you do not want to change logic when changing a displayed name!)
Coding in ASP.NET allows to have a more readable and maintainable code.
NOTE: keep in mind that user should know or will be affected by LIKE special characters.
I assuming your parameters are nullable, therefore you can just do like this
SELECT * FROM student
WHERE name LIKE ( CASE WHEN #condition = 'startswith' THEN #searchtext + '%'
WHEN #condition = 'endswith' THEN '%'+#searchtext
ELSE '%'+#searchtext+'%'
END
) AND
(#searchclass IS NULL OR studentClass = #searchclass)
#searchclass IS NULL is for you to check is the parameter's value and it wont clash even if your #searchclass is NULL
Hope it help ya.
Refer below updated stored procedure with Class filter.
Change Class column based on exact column name:
ALTER PROCEDURE sp_searchedstudentrecords
(
#condition varchar(20),
#searchtext varchar(50),
#searchclass int
)
AS
BEGIN
IF (#condition = 'startswith')
SELECT * FROM student WHERE name like #searchtext+ '% ' AND Class = #searchclass
ELSE IF (#condition = 'endswith')
SELECT * FROM student WHERE name like '%' +#searchtext AND Class = #searchclass
ELSE
SELECT * FROM student WHERE name like '%' +#searchtext+ '%' AND Class = #searchclass
END

SQL Search Query With Null and ''

I have a query that I'm building for an application. The database is setup in SQL Server 2008. I want to use a query similar to below, however, I will be using this 'Where' clause for about 4 other columns using the same requirements. Is this the appropriate way to test for null or '' in a column that is VarChar(255) and does allow nulls.
Ideally, if the variable #UutSerialNumber is null or empty (''), I want all the results, but if it is not, I want to use the 'LIKE' clause. Is this the proper way of doing this and will it work? It seems to work until I start adding more columns to the Where clause.
Also, how would I handle a "text" datatype using the same type of query?
SELECT DeviceName, UutStatus
FROM MyTable
WHERE (UutSerialNumber LIKE '%' + #UutSerialNumber + '%' OR UutSerialNumber LIKE '%%' AND (#UutSerialNumber = '' OR #UutSerialNumber IS NULL)) AND ...
Help is appreciated. Thanks everyone!
It amy seem like duplication of SQL but the best way to do this is in terms of performace is using IF ... ELSE
IF ISNULL(#UutSerialNumber, '') = ''
BEGIN
SELECT DeviceName, UutStatus
FROM MyTable
-- MORE EXPRESSIONS
END
ELSE
BEGIN
SELECT DeviceName, UutStatus
FROM MyTable
WHERE (UutSerialNumber LIKE '%' + #UutSerialNumber + '%'
-- MORE EXPRESSIONS
END
It can be done within the WHERE clause if you are doing it on multiple columns and the query you posted wasn't far off it was just missing additional parenthesis along with having a redundant clause.
SELECT DeviceName, UutStatus
FROM MyTable
WHERE (ISNULL(#UutSerialNumber, '') = '' OR UutSerialNumber LIKE '%' + #UutSerialNumber + '%')
AND (ISNULL(#AnotherParameter, '') = '' OR AnotherColumn LIKE '%' + #AnotherParameter + '%')
Convert the text type to VARCHAR(MAX).
as a footnote, I personally would use the CHARINDEX rather than concatenating strings in the like:
WHERE (ISNULL(#UutSerialNumber, '') = '' OR CHARINDEX(#UutSerialNumber, UutSerialNumber) > 0)
This is nothing more than a footnote however as I have done no performance testing, I just think it is easier on the eye!
SELECT DeviceName, UutStatus
FROM MyTable
WHERE ((#UutSerialNumber = '') OR (#UutSerialNumber is null)) OR (UutSerialNumber like #UutSerialNumber)
add '%' to the last #UutSerialNumber if you think you need

SQL Server Compare similar tables with query

Simple concept we are basically doing some auditing, comparing what came in, and what actually happened during processing. I am looking for a better way to execute a query that can do side by side table comparisons with columns that are slightly differnt in name and potentialy type.
DB Layout:
Table (* is the join condition)
Log (Un-altered data record.)
- LogID
- RecordID*
- Name
- Date
- Address
- Products
- etc.
Audit (post processing record)
- CardID*
- CarName
- DeploymentDate
- ShippingAddress
- Options
- etc.
For example this would work if you look past the annoying complexity to write, and performance issues.
The query just joins the left and right and selects them as strings. Showing each field matched up.
select
cast(log.RecordID as varchar(40)) + '=' + cast(audit.CardID as varchar(40),
log.Name+ '=' + audit.Name ,
cast(log.Date as varchar(40)) + '=' + cast(audit.DeploymentDate as varchar(40),
log.Address + '=' + audit.ShippingAddress,
log.Products+ '=' + audit.Options
--etc
from Audit audit, Log log
where audit.CardID=log.RecordId
Which would output something like:
1=1 Test=TestName 11/09/2009=11/10/2009 null=My Address null=Wheels
This works but is extremely annoying to build. Another thing I thought of was to just alias the columns, union the two tables, and order them so they would be in list form. This would allow me to see the column comparisons. This comes with the obvious overhead of the union all.
ie:
Log 1 Test 11/09/2009 null, null
Audit 1 TestName 11/10/2009 My Address Wheels
Any suggestions on a better way to audit this data?
Let me know what other questions you may have.
Additional notes. We are going to want to reduce the unimportant information so in some cases we might null the column if they are equal (but i know its too slow)
case when log.[Name]<>audit.[CarName] then (log.[Name] + '!=' + audit.[CarName]) else null end
or if we are doing the second way
nullif(log.[Name], audit.[CarName]) as [Name]
,nullif(audit.[CarName], log.[Name]) as [Name]
I've found the routine given here by Jeff Smith to be helpful for doing table comparisons in the past. This might at least give you a good base to start from. The code given on that link is:
CREATE PROCEDURE CompareTables(#table1 varchar(100),
#table2 Varchar(100), #T1ColumnList varchar(1000),
#T2ColumnList varchar(1000) = '')
AS
-- Table1, Table2 are the tables or views to compare.
-- T1ColumnList is the list of columns to compare, from table1.
-- Just list them comma-separated, like in a GROUP BY clause.
-- If T2ColumnList is not specified, it is assumed to be the same
-- as T1ColumnList. Otherwise, list the columns of Table2 in
-- the same order as the columns in table1 that you wish to compare.
--
-- The result is all records from either table that do NOT match
-- the other table, along with which table the record is from.
declare #SQL varchar(8000);
IF #t2ColumnList = '' SET #T2ColumnList = #T1ColumnList
set #SQL = 'SELECT ''' + #table1 + ''' AS TableName, ' + #t1ColumnList +
' FROM ' + #Table1 + ' UNION ALL SELECT ''' + #table2 + ''' As TableName, ' +
#t2ColumnList + ' FROM ' + #Table2
set #SQL = 'SELECT Max(TableName) as TableName, ' + #t1ColumnList +
' FROM (' + #SQL + ') A GROUP BY ' + #t1ColumnList +
' HAVING COUNT(*) = 1'
exec ( #SQL)
Would something like this work for you:
select
(Case when log.RecordID = audit.CardID THEN 1 else 0) as RecordIdEqual,
(Case when log.Name = audit.Name THEN 1 else 0) as NamesEqual ,
(Case when log.Date = audit.DeploymentDate THEN 1 else 0) as DatesEqual,
(Case when log.Address = audit.ShippingAddress THEN 1 else 0) as AddressEqual,
(Case when log.Products = audit.Options THEN 1 else 0) as ProductsEqual
--etc
from Audit audit, Log log
where audit.CardID=log.RecordId
This will give you a break down of what's equal based on the column name. Seems like it might be easier than doing all the casting and having to interpret the resulting string...

Writing SQL code: same functionality as Yell.com

Can anyone help me with the trying to write SQL (MS SqlServer) - I must admit this is not by best skill.
What I want to do is exactly the same functionality as appears for the search boxes for the Yell website i.e.
Search for company type
AND/OR company name
AND/OR enter a company name
in a Location
if anyone can suggest the SQL code you would need to write in order to get the same functionality as Yell - that would be great.
Typically, one does something like this:
-- All these are NULL unless provided
DECLARE #CompanyType AS varchar
DECLARE #CompanyName AS varchar
DECLARE #Town AS varchar
SELECT *
FROM TABLE_NAME
WHERE (#CompanyType IS NULL OR COMPANY_TYPE_COLUMN LIKE '%' + #CompanyType + '%')
AND (#CompanyName IS NULL OR COMPANY_NAME_COLUMN LIKE '%' + #CompanyName + '%')
AND (#Town IS NULL OR TOWN_COLUMN LIKE '%' + #Town + '%')
Or this (only match start of columns with the wildcards):
-- All these are NULL unless provided
DECLARE #CompanyType AS varchar
DECLARE #CompanyName AS varchar
DECLARE #Town AS varchar
SELECT *
FROM TABLE_NAME
WHERE (#CompanyType IS NULL OR COMPANY_TYPE_COLUMN LIKE #CompanyType + '%')
AND (#CompanyName IS NULL OR COMPANY_NAME_COLUMN LIKE #CompanyName + '%')
AND (#Town IS NULL OR TOWN_COLUMN LIKE #Town + '%')
Can you provide the database layout (schema) that the sql would run against? It would be necessary to give you an exact result.
But generally speaking what you are looking for is
SELECT * FROM tablename WHERE companyType = 'type' OR companyName = 'companyName'
What you need first is not SQL code, but a database design. Only then does it make any sense to start writing SQL.
A simple table schema that matches Yell's functionality might be something like:
CREATE TABLE Company (
company_id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
company_name VARCHAR(255) NOT NULL,
location VARCHAR(255) NOT NULL
)
and then you'd search for it by name with SQL like:
SELECT * FROM Company WHERE company_name like '%text%'
or by location like:
SELECT * FROM Company WHERE location = 'Location'
Of course, a real-world location search would have to use either exact city and state, or a zip code lookup, or some intelligent combination thereof. And a real table would then have lots more fields, like descriptions, etc. But that's the basic idea.