I'm wondering if it's possible to include mathematical operators and situations in a multivariable parameter.
In my example, I'm looking to have the freedom to enter 'Overdue' 'Less than one day' or 'More than one day' as #SLA_Days.
Currently, I can enter any of these one variables and it will return a result.
if #sla_days = 'Overdue'
BEGIN
SELECT #sql = #sql + 'and sla_days < 0'
END
ELSE
if #sla_days = 'Less than one day'
BEGIN
SELECT #sql = #sql + 'and sla_days <1 and sla_days >0'
END
ELSE
if #sla_days = 'More than one day'
BEGIN
SELECT #sql = #sql + 'and sla_days > 1'
END
EXEC sp_exectuesql #SQL
I do have a function that I've created that will look a comma delimited string and pull out variables. I do not need help in creating this
What I do need help is, is it possible to enter #SLA_days = 'Overdue,Less than one day,More than one day' and still have it recognize these rules?
Therefore, if I selected Overdue and less than one day, it would return both values where sla_days < 0 and sla days < 1
You don't need a function to pull out variables. This will perform much better.
The trick for your specific problem is to use OR instead of AND, because the value in a column could never be, for example, > 0 AND < 0. Also I add commas to each side of the variable so that conditions can be identified in any order. Note, though, that it will not find values if there are spaces between the commas as well - you'll have to adjust for that.
SET #SLA_days = ',' + #SLA_days + ',';
SET #sql = #sql + ' (1=2 '
+ CASE WHEN #SLA_days LIKE '%,Overdue,%'
THEN ' OR (sla_days < 0)' ELSE '' END
+ CASE WHEN #SLA_days LIKE '%,Less than one day,%'
THEN ' OR (sla_days < 1 AND sla_days > 0)' ELSE '' END
+ CASE WHEN #SLA_days LIKE '%,More than one day,%'
THEN ' OR (sla_days > 1)' ELSE '' END + ')';
Finally, do you really need to pass these big ugly strings to the database? Presumably the users are selecting from a multi-select or checking boxes, in which case you could use much tidier coefficients to represent each case.
Related
I have a requirement which needs to find out consolidated error report of all columns containing error report. Is there any function or any ways to do this in SQL Server?
I tried this using a CASE statement but it only gives error report for one column.
I need the result like this after applying filter or procedure
You can use CASE:
select
row,
case when length(name) > 10
then 'Name max=10 Present=' + length(name) + '; '
else '' end +
case when length(place) > 10
then 'Place max=10 Present=' + length(place) + '; '
else '' end +
case when length(address) > 10
then 'Address max=10 Present=' + length(address) + '; '
else '' end as error
from t
I am trying to emulate the PL/SQL DECODE() function in T-SQL:
CREATE FUNCTION [dbo].[fnDecode]
(
#condition AS BIT,
#trueVal AS VARCHAR(2000),
#falseVal AS VARCHAR(2000)
)
RETURNS VARCHAR(2000)
WITH EXEC AS CALLER AS
BEGIN
RETURN CASE #condition
WHEN 1 THEN #trueVal
ELSE #falseVal
END
END
GO
The PL/SQL fragment I'm trying to port to T-SQL is this:
CASE pcr.person_type
WHEN 'N'
THEN
npcr.first_name
|| DECODE (npcr.middle_name,
NULL, '',
' ' || npcr.middle_name)
|| ' '
|| npcr.last_name
WHEN 'L'
THEN
lpcr.name
END
I want to call the scalar function defined above in a CASE statement like this:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ dbo.fnDecode(npcr.middle_name IS NULL, '', ' ' + npcr.middle_name)
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
I cannot store the result of the fnDecode() function into a variable because the rows are coming from some joined tables (and there are multiple calls to fnDecode() in the queries I'm porting)
We're using SQL Server 2012 and 2014.
Porting procedural approaches "as it is" is not a good practice at all. This is not a PHP, C# or even PL/SQL. Furthermore, in the case described you don't even need any function calls. NULL and empty string handling in scenarios mentioned above is very simple and does not require any procedural methods.
There are functions NULLIF, ISNULL, COALESCE, CASE statement. Everything you need is to check if something is true or false, null or not.Scalar UDF calls for every row may (and will) result in serious performance issues.Check this out:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ IsNull(' ' + npcr.middle_name, '')
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
even if you have disabled ANSI_NULLS and CONCAT_NULL_YIELD_NULL options and dont' wish to give any chance to server to do anything wrong you can use case and this approach will be much better than calling a function:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ case when npcr.middle_name is NULL then '' else ' ' + npcr.middle_name end
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
if there are empty stings allowed this code can work well (with regular null option set):
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ IsNull(' ' + NullIf(npcr.middle_name, ''), '')
+ IsNull(' ' + NullIf(npcr.last_name, ''), '')
WHEN 'L' THEN lpcr.name
END
Yes, it's certainly possible to call scalar functions from within CASE expressions (and many other places).
The issue you're experiencing relates to the first parameter. BIT is a numeric data type. Not a boolean and, in fact, SQL Server does not have an exposed boolean data type in T-SQL. So you cannot make the first parameter of your fDecode function a boolean, nor can you pass the result of evaluating a predicate, such as npcr.middle_name = NULL in a place that expects to accept a bit.
Something like this should execute:
CASE pcr.person_type
WHEN 'N' THEN npcr.first_name
+ dbo.fnDecode(CASE WHEN npcr.middle_name = NULL THEN 1 ELSE 0 END, '', ' ' + npcr.middle_name)
+ ' '
+ npcr.last_name
WHEN 'L' THEN lpcr.name
END
(Although you may also need to insert an explicit cast also)
But this makes the cure look worse than the curse.
In any case, you can just use the built in IIF function rather than fDecode. Because it's built in, it doesn't play by the same rules that you have to play by, and in fact its first parameter is a boolean expression.
Ok so I have searched for an answer to this on Technet, to no avail.
I just want to print an integer variable concatenated with two String variables.
This is my code, that doesn't run:
print 'There are ' + #Number + ' alias combinations did not match a record'
It seems like such a basic feature, I couldn't imagine that it is not possible in T-SQL. But if it isn't possible, please just say so. I can't seem to find a straight answer.
declare #x INT = 1 /* Declares an integer variable named "x" with the value of 1 */
PRINT 'There are ' + CAST(#x AS VARCHAR) + ' alias combinations did not match a record' /* Prints a string concatenated with x casted as a varchar */
Numbers have higher precedence than strings so of course the + operators want to convert your strings into numbers before adding.
You could do:
print 'There are ' + CONVERT(varchar(10),#Number) +
' alias combinations did not match a record'
or use the (rather limited) formatting facilities of RAISERROR:
RAISERROR('There are %i alias combinations did not match a record',10,1,#Number)
WITH NOWAIT
If you don't want to manually cast types, you can use the CONCAT-function for this.
PRINT CONCAT('There are ', #Number, ' alias combinations did not match a record')
You can't combine a character string and numeric string. You need to convert the number to a string using either CONVERT or CAST.
For example:
print 'There are ' + cast(#Number as varchar) + ' alias combinations did not match a record'
or
print 'There are ' + convert(varchar,#Number) + ' alias combinations did not match a record'
Double check if you have set and initial value for int and decimal values to be printed.
This sample is printing an empty line
declare #Number INT
print 'The number is : ' + CONVERT(VARCHAR, #Number)
And this sample is printing -> The number is : 1
declare #Number INT = 1
print 'The number is : ' + CONVERT(VARCHAR, #Number)
You may try this one,
declare #Number INT = 5
print 'There are ' + CONVERT(VARCHAR, #Number) + ' alias combinations did not match a record'
I have a lengthy stored procedure that builds a query string. It works fine until I add in a 'LIKE' description field (text) which has a wildcard in it, see below:
IF #AdDescription IS NOT NULL
IF #AdSection IS NOT NULL
BEGIN
SET #SQL = #SQL + #Wand + 'na.Section = '' + #AdDescription + '''
SET #Wand = ' AND '
END
ELSE
BEGIN
SET #SQL = #SQL + #Wand + '(na.AdDesc LIKE ''' + #AdDescription + '%'')'
SET #Wand = ' AND '
END
I've tried a few variations but as soon as #AdDescription has anything in it it fails. Is there something obvious that I am missing?
You are missing an apostrophe in your first "SET #SQL" line. There should be 3 apostrophes before you add the #AdDescription. The color coding in your code above shows this problem. The plus signs are red instead of black.
Try using print to see the SQl you have created, then you will likely see the error. And try really hard to avoid dynamic sql, it's hard to maintain, test, and debug properly.
Instead of exec the SQl just have it do:
Print #SQL
This will print the SQL Statement.
We usually havea debug parameter on any stored proc that uses dynamic SQl abd if it is set to 1, it prints the SQL and if it is set to 0 (the default), it executes the SQL. This makes it easier to see what is being created for a set of values later when the proc fails in production becasue of some obscure condition you didn't consider.
YOu can also get the SQl executed by running profiler, but usually it's simpler to just run with the same values in debug mode.
Edit Maybe it's just the quotes? I've added some spaces so the escaping is clearer.
IF #AdDescription IS NOT NULL
IF #AdSection IS NOT NULL
BEGIN
SET #SQL = #SQL + #Wand
+ 'na.Section = ' ''' + #AdDescription + ''' '
SET #Wand = ' AND '
END
ELSE
BEGIN
SET #SQL = #SQL + #Wand
+ '(na.AdDesc LIKE ' ''' + #AdDescription + '%'' )'
END
I have a Proc that was coded in Dynamic SQl for one of my Application. It is using to search the Applicants with their last name. Right now it is searching applicants with either their first 2 digits of their last name or full last name. But i have a problem searching Applicants that have Apostrophe in their last name(Example O'Connor). If the client try to search applicant with O' or O'Connor it is throwing an error. They want to search every Applicant with or without Apostrophe in their last name. Please Help I tried everything, but its not working. Below is my search code that using in the Proc to pull applicants:
Add wildcards if necessary
if Rtrim(#FirstName) <> ''
begin
If(Len(#FirstName) < 30) and (CharIndex('%', #FirstName) = 0) and #FirstName != ''
Set #FirstName = char(39) + #FirstName + '%' + char(39)
end
if Rtrim(#LastName) <> ''
begin
If(Len(#LastName) < 60) and (CharIndex('%', #LastName) = 0) and #LastName != ''
Set #LastName = Char(39) + #LastName + '%' + char(39)
end
Now build dinamically the filter base on input parameters
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Rtrim(#LastName)
You need to escape the apostrophe in the input string (basically replace a single ' with two '') as you build your SQL string
You need to pay attention to this anywhere you choose to pass user input to a SQL server database as its a security issue (SQL Injection Attacks) c.f. Bobby Tables
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Replace(Rtrim(#LastName),'''','''''') + ''
My suggestion is to write the query to contain an alternate column to be used for filtering with the apostrophe/single quote replaced by any special character such as a #. This allows you to leave the original column intact in case you want to display it.
To do that in SQL Server, you could do something like this:
Select
tbl.strName_Last,
REPLACE(tblOrder.strName_Last, '''','#')) as StrLastNameForFilter
....
Then change your code to filter based on this alternate column, and in the user-provided filter string, replace the apostrophe/single quote with the special character.