Below consider below extract from a query:
FROM d_employee e
LEFT JOIN [dbo].[t_etl_employee] t
ON e.customer_nr = t.employee_nr
AND (t.dep_id = #dep_id OR #dep_id IS NULL)
Requirement is to replace "AND (t.dep_id = #dep_id OR #dep_id IS NULL)" in above query by dynamic sql or handle with IF statement but in any case OR should be avoided.
Thanks All! I will try to go ahead with COALESCE. Sorry to add a bit more to the question.
FROM d_employee e
LEFT JOIN [dbo].[t_etl_employee] t
ON e.customer_nr = t.employee_nr
AND (COALESCE(#dep_id, t.dep_id) =t.dep_id)
AND ( t.status = 0)
WHERE e.end_date = N'99991130'
AND (t.employee_nr IS NULL
OR t.employee_shortname <> e.employee_shortname
OR t.employee_description <> e.employee_description
OR t.employee_address_1 <> e.t.employee_address_1
OR t.nce_code <> e.nce_code
OR (t.rt_code IS NULL AND e.rt_code IS NOT NULL)
OR (t.rt_code IS NOT NULL AND e.rt_code IS NULL)
OR t.is_rated <> e.is_rated
OR t.is_default <> e.is_default
)
Additional requirement suggested is:
◾splitting the AND and OR statements in the where clause…… then left join could be INNER join for the OR statements (separate statement for left join and IS NULL check)…. not sure how will I split it? Any help is much appreciated.
Try COALESCE:
...
AND COALESCE(#dep_id, t.dep_id) = t.dep_id
I don't know what's wrong with your original query - but a dynamic-sql version of it would be this:
DECLARE #cmd NVARCHAR(MAX) = ''
DECLARE #dep_id TINYINT = NULL
SET #cmd = 'SELECT e.customer_nr
FROM d_employee e
LEFT JOIN [dbo].[t_etl_employee] t
ON e.customer_nr = t.employee_nr'
+ IIF(#dep_id IS NOT NULL,' AND t.dep_id = ' + CAST(#dep_id AS NVARCHAR(3)),'')
PRINT #cmd
EXECUTE sp_executesql #cmd
Related
My stored procedure is currently using Is Null Or Exist logic combined with an inner query to filter out the records. The stored procedure is converting multiple comma-separated input values to temp tables (in the production scenario, the input record count will be much higher). And the inner query is using these temp tables for filter conditions. Due to the concern over query execution time would like to change the existing inner-query with an alternate (like left join). But need to retain the same Is Null Or Exist logic. Any suggestions?
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
WHERE (#SelectedOfferes IS NULL
OR (EXISTS (SELECT 1 FROM #SelectedOfferes OFR
WHERE OFR.DiscountCode = P.DiscountCode)))
AND (#SelectedBrandCode IS NULL
OR (EXISTS (SELECT 1 FROM #BrandCode BC
WHERE BC.BrandCode = P.BrandCode)))
AND (#CategoryCode IS NULL
OR (EXISTS (SELECT 1 FROM #CategoryCode CAT
WHERE CAT.CategoryCode = P.CategoryCode)))
Dynamic SQL version
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
The below example should work the same as what you supplied but should be faster since it removes the ORs and the correlated subqueries from the WHERE clause. I'm not a fan of using dynamic SQL but sometimes it is the best way to get the job done. Maybe someone else can come up with a non-dynamic solution that works as well or better.
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
DECLARE #SQL NVarchar(4000);
SET #SQL = N'SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode'
IF #SelectedOfferes IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode';
IF #SelectedBrandCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode';
IF #CategoryCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode';
EXEC sys.sp_executesql #stmt = #SQL;
This method doesn't quite do what the OP wanted but is valid in many other cases
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
But either way the below change to your last query should help quite a bit. The IS NULL parts aren't needed since it is a LEFT JOIN and the table will be empty if the variable it is built with is NULL, so you get the same result with less work for the engine.
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
LEFT JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode
LEFT JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode
LEFT JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode
I have a stored procedure that is showing a list of doctors and their details based on the sub-department they belong to. Below is the stored proc:
CREATE PROCEDURE SP_BILL_FOOTER_DOCTOR
#subDepartmentId int
AS
BEGIN
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId
END
Below is the link of the output that follows when procedure executes :
I want to know is it possible to convert the rows in different column. Like the output has 6 columns and 2 rows, I want all the data in 1 row with 12 columns. Below is the sample output:
It would be of great help if somebody could guide me on how to do it. I have understood that by using Pivot in Sql, I can achieve this, but none I have found to my specific case.
Please have a look at updated code below:
select *, row_number() over(order by employee_name) rownum into #a from (
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId )a
declare #iterator int=1
declare #string varchar(max)= ''
declare #string2 varchar(max)= ''
declare #string3 varchar(max)= ''
declare #string4 varchar(max)= ''
declare #exec varchar(max)
while #iterator<=(select max(rownum) from #a)
begin
select #string2=
'['+cast(#iterator as varchar(max))+'].'+ 'EMPLOYEE_NAME'+
',['+cast(#iterator as varchar(max))+'].'+'EMPLOYEE_TYPE_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SPECIALITY_DESCRIPTION' +
',['+cast(#iterator as varchar(max))+'].'+'SUB_DEPARTMENT_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE'+
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE_PIC'
from #a where rownum=#iterator
select #string= #string+#string2
select #string4=
case when #string4='' then
#string4+'['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) else
#string4+' and ['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) end
select #string3= case when #iterator>1 then #string3+' cross join #a ['+ cast(#iterator as varchar(max))+']' else '' end
set #iterator=#iterator+1
end
select #exec = 'select distinct'+ left(#string, len(#string)-1) +' from #a [1] '+#string3+ ' where '+ #string4
exec(''+#exec+'')
This isn't really an answer but a demonstration of how much using aliases can improve the legibility of your queries. Believe it or not this EXACTLY the same thing you posted. I just used aliases so you can read this instead of looking at a wall of text. The only actual change was to use a cross join instead of a left join on 1 = 1.
SELECT e.EMPLOYEE_NAME,
et.EMPLOYEE_TYPE_NAME,
s.DOCTOR_SPECIALITY_DESCRIPTION,
sd.SUB_DEPARTMENT_NAME,
e.DOCTOR_SIGNATURE,
CASE WHEN e.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH, '') + e.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE e
INNER JOIN HETC_PAR_EMPLOYEE_TYPE et ON et.EMPLOYEE_TYPE_ID = e.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY s ON s.DOCTOR_SPECIALITY_ID = e.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT dd ON dd.EMPLOYEE_ID = e.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT sd ON sd.SUB_DEPARTMENT_ID = dd.SUB_DEPARTMENT_ID
cross join
(
SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH p
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT a ON p.TYPE_OF_DOCUMENT_ID = a.TYPE_OF_DOCUMENT_ID
WHERE a.TYPE_OF_DOCUMENT_CODE='DSI'
) AS DOC_SIGNATURE_PIC
WHERE sd.SUB_DEPARTMENT_ID = #subDepartmentId
For the question at hand it is hard to tell what you are really wanting here. Maybe some conditional aggregation in combination with ROW_NUMBER. Or a PIVOT. You would need to post more details for this. Here is a great place to start. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/
I got a SQL statement which uses some parameters to filter the output.
Looking like this:
ALTER PROCEDURE [dbo].[spGetPerson]
#Vorname varchar(50),
#Nachname varchar(50),
#FirmaID int,
#AbteilungID int,
#ArbeitsortID int,
#FunktionID int
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
Select
p.Vorname, p.Nachname, ar.Arbeitsort, fi.Firma,
ab.Abteilung, fu.Funktion
From
tblPerson p
inner join
tblArbeitsort ar on ar.ArbeitsortID = p.Arbeitsort_fk
inner join
tblFirmaHatAbteilungUndPersonHatFunktion zt on zt.Person_fk = p.PersonID
inner join
tblFirma fi on fi.FirmaID = zt.Firma_fk
inner join
tblAbteilung ab on ab.AbteilungID = zt.Abteilung_fk
inner join
tblFunktion fu on fu.FunktionID = zt.Funktion_fk
Where
p.Vorname = #Vorname
AND p.Nachname = #Nachname
AND fi.FirmaID = #FirmaID
AND ab.AbteilungID = #AbteilungID
AND ar.ArbeitsortID = #ArbeitsortID
AND fu.FunktionID = #FunktionID
END
I'm joining some stuff together but that's not important.
As you can see at the end I use every parameter in my WHERE clause. What I would like to do is, if one parameter is missing the related "where" falls away.
As an example if #Nachname is missing the statement should look like this:
Where
p.Vorname = #Vorname
AND fi.FirmaID = #FirmaID
AND ab.AbteilungID = #AbteilungID
AND ar.ArbeitsortID = #ArbeitsortID
AND fu.FunktionID = #FunktionID
How do I do this?
Another way that I have found coming to my rescue in these cases is as below. How it works is simple. If the needed parameter is not null it will be used else the column is matched with itself causing engine to ignore that join as WHERE 1=1 type joins are skipped. Hope this helps
Where
p.Vorname = COALESCE(#Vorname, p.Vorname)
AND fi.FirmaID = COALESCE(#FirmaID ,fi.FirmaID )
AND ab.AbteilungID = COALESCE(#AbteilungID ,ab.AbteilungID )
AND ar.ArbeitsortID = COALESCE(#ArbeitsortID,ar.ArbeitsortID )
AND fu.FunktionID = COALESCE(#FunktionID,fu.FunktionID)
The typical way to do this is to use logic like this:
Where (p.Vorname = #Vorname or #Vorname is null) AND
(p.Nachname = #Nachname or #Nachname is null) AND
(fi.FirmaID = #FirmaID or #FirmaID is null) AND
(ab.AbteilungID = #AbteilungID or #AbteilungID is null) AND
(ar.ArbeitsortID = #ArbeitsortID or #ArbeitsortID is null) AND
(fu.FunktionID = #FunktionID or #FunktionID is null)
One note: the use of such complex where clauses can affect the optimization strategies for the query. If performance is a big issue (and you have indexes on the columns in the where clause used for the conditions), then you might want to use dynamic SQL instead. That is, you would construct the where clause based on the parameters that have values, rather than checking for NULL at run-time.
Depending on your tables sizes (number of records) and how the filters are populated (maybe you have only two filters specified most of the time, a dynamic SQL may lead to better results):
DECLARE #SQL NVARCHAR(MAX) = N'
Select p.Vorname, p.Nachname, ar.Arbeitsort, fi.Firma, ab.Abteilung, fu.Funktion From tblPerson p
inner join tblArbeitsort ar on ar.ArbeitsortID = p.Arbeitsort_fk
inner join tblFirmaHatAbteilungUndPersonHatFunktion zt on zt.Person_fk = p.PersonID
inner join tblFirma fi on fi.FirmaID = zt.Firma_fk
inner join tblAbteilung ab on ab.AbteilungID = zt.Abteilung_fk
inner join tblFunktion fu on fu.FunktionID = zt.Funktion_fk
WHERE 1 = 1'
IF (#Vorname IS NOT NULL) #SQL = #SQL + ' AND p.Vorname = #Vorname'
IF (#Nachname IS NOT NULL) #SQL = #SQL + ' AND p.Nachname = #Nachname'
-- other if conditions come here
EXEC sp_executesql #SQL, N'#Vorname VARCHAR(50), #Nachname VARCHAR(50)',
#Vorname = #Vorname, #Nachname = #Nachname
Although dynamic SQLs do not benefit from some performance improvements, the fact that your WHERE is much more simpler (multiple ORs are not performance friendly) might lead to better results.
You can not easily and efficiently do that and this is a nice example why running SP's for queries is a dead end.
The best you can do is:
WHERE ([x] LIKE #x AND #x IS NOT NULL)
combined with an OPTION RECOMPILE on the statement to avoid parameter sniffing to determine a possibly bad query plan.
I'd like to select a particular value from a table while using an information from another database that is set based on a current database's value.
So a select case to find the operator code and set the DB path.. then use the same path and collate the result.
DECLARE #DB varchar (1000)
CASE
WHEN #Operator= 1 THEN SET #DB = '{SERVERNAME\ENTITY\DBNAME}'
WHEN #Operator= 2 THEN SET #DB = '{SERVERNAME2\ENTITY2\DBNAME2}'
WHEN #Operator= 3 THEN SET #DB = '{SERVERNAME3\ENTITY3\DBNAME3}'
Select transItem_item collate SQL_Latin1General_CI_AS
FROM Group_Transactions
INNER JOIN #DB.Table_Trans
ON (transItem.item_id collate SQL_Latin1General_CI-AS = Table_Trans.item_id)
Where ---Condition
Control flow method (likely to be the most efficient):
IF #Operator = 1
BEGIN
SELECT stuff
FROM Group_Transactions
INNER
JOIN "Server1\Instance1".Database1.Schema.Table_Trans
ON Group_Transactions... = Table_Trans...
WHERE things...
;
END
ELSE IF #Operator = 2
BEGIN
SELECT stuff
FROM Group_Transactions
INNER
JOIN "Server2\Instance2".Database2.Schema.Table_Trans
ON Group_Transactions... = Table_Trans...
WHERE things...
;
END
ELSE IF #Operator = 3
BEGIN
SELECT stuff
FROM Group_Transactions
INNER
JOIN "Server3\Instance3".Database3.Schema.Table_Trans
ON Group_Transactions... = Table_Trans...
WHERE things...
;
END
;
Single [conditional] query method:
SELECT Group_Transactions.stuff
, trans1.other_thing As other_thing1
, trans2.other_thing As other_thing2
, trans3.other_thing As other_thing3
, Coalesce(trans1.other_thing, trans2.other_thing, trans3.other_thing) As other_thing
FROM Group_Transactions
LEFT
JOIN "Server1\Instance1".Database1.Schema.Table_Trans As trans1
ON trans1... = Group_Transactions...
AND trans1.things...
AND #Operator = 1
LEFT
JOIN "Server2\Instance2".Database2.Schema.Table_Trans As trans2
ON trans2... = Group_Transactions...
AND trans2.things...
AND #Operator = 2
LEFT
JOIN "Server3\Instance3".Database3.Schema.Table_Trans As trans3
ON trans3... = Group_Transactions...
AND trans3.things...
AND #Operator = 3
;
If this is TSQL (I am guessing from your colation names) then you are best trying out OPENQUERY to run your join against another database server. If you are querying a database on the same server you could build your query up as a parameter and then run it using EXEC.
Gvee's Control Flow method may be a verbose, but it would work. You might want to create a look up table like my #tbl_Databases if you have a bunch of databases. Here's a dynamic SQL solution:
DECLARE #Operator INT = 1,
#DB VARCHAR(1000);
DECLARE #tbl_Databases TABLE (ID INT IDENTITY(1,1),DB VARCHAR(1000))
INSERT INTO #tbl_Databases(DB)
VALUES ('{SERVERNAME\ENTITY\DBNAME}'),('{SERVERNAME2\ENTITY2\DBNAME2}'),('{SERVERNAME3\ENTITY3\DBNAME3}');
SELECT #DB = DB
FROM #tbl_Databases
WHERE ID = #Operator
SELECT #DB
SELECT
(
'SELECT transItem_item COLLATE SQL_Latin1General_CI_AS
FROM Group_Transactions
INNER JOIN ' + #DB + '.dbo.Table_Trans
ON (transItem.item_id collate SQL_Latin1General_CI-AS = Table_Trans.item_id)
Where 1 = 1'
)
I have a stored procedure. In this stored procedure I have to check that a particular parameter is not null. How can I do this? I wrote this:
ALTER PROCEDURE [dbo].[GetReelListings]
#locationUrlIdentifier VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
declare #Sql varchar(max)=''
SET #Sql = 'SELECT CategoryName, CategoryUrlIdentifier, LocationUrlIdentifier, Directory.* FROM (SELECT ROW_NUMBER() OVER (PARTITION BY Category.Name ORDER BY CASE WHEN '''+ #locationUrlIdentifier + ''' = Location.UrlIdentifier THEN 1 ELSE CASE WHEN ''' + #locationUrlIdentifier + ''' IS NULL AND Directory.LocationId IS NULL THEN 0 ELSE 2 END END, Directory.SortOrder ) AS ''RowNo'', Category.Name AS CategoryName, Category.UrlIdentifier AS CategoryUrlIdentifier, dbo.Location.UrlIdentifier AS LocationUrlIdentifier, Directory.DirectoryId, CASE WHEN ''' + #locationUrlIdentifier + ''' = Location.UrlIdentifier THEN 1 ELSE CASE WHEN ''' + #locationUrlIdentifier + ''' IS NULL AND Directory.LocationId IS NULL THEN 0 ELSE 2 END END AS CategoryOrder FROM dbo.Directory INNER JOIN dbo.Category ON Directory.CategoryId = Category.CategoryId LEFT OUTER JOIN dbo.Location ON dbo.Directory.LocationId = location.Location_ID ) AS content INNER JOIN dbo.Directory ON content.DirectoryId = Directory.DirectoryId WHERE content.RowNo =1 '
if (#locationUrlIdentifier is null)
begin
SET #Sql = #Sql + ' and 1=1'
end
else
begin
SET #Sql = #Sql + ' and CategoryOrder = 1 '
end
print #SQl
EXECUTE (#Sql)
END
This will work in SQL but this will return a null Dataset in Codebehind.
Whenever you join strings and NULLs together, the result is NULL. By the time you're asking about whether the variable is NULL, you've already done this:
' + #locationUrlIdentifier + '
Several times. If it's NULL, so will #Sql be.
You might want to consider using COALESCE to replace the NULL with a suitable replacement (e.g. an empty string):
' + COALESCE(#locationUrlIdentifier,'') + '
You also still have a logic error on your final construction. If the variable is NULL, you'll have a where clause saying:
WHERE content.RowNo =1 1=1
Which isn't valid. I don't think you should be appending anything.
I'm also not clear on why you're doing this as dynamic SQL. The below seems to be an equivalent query which can be executed directly:
SELECT
CategoryName,
CategoryUrlIdentifier,
LocationUrlIdentifier,
Directory.*
FROM
(SELECT
ROW_NUMBER() OVER (
PARTITION BY Category.Name ORDER BY
CASE
WHEN #locationUrlIdentifier = Location.UrlIdentifier THEN 1
WHEN #locationUrlIdentifier IS NULL AND Directory.LocationId IS NULL THEN 0
ELSE 2
END,
Directory.SortOrder
) AS RowNo,
Category.Name AS CategoryName,
Category.UrlIdentifier AS CategoryUrlIdentifier,
dbo.Location.UrlIdentifier AS LocationUrlIdentifier,
Directory.DirectoryId,
CASE
WHEN #locationUrlIdentifier = Location.UrlIdentifier THEN 1
WHEN #locationUrlIdentifier IS NULL AND Directory.LocationId IS NULL THEN 0
ELSE 2
END AS CategoryOrder
FROM
dbo.Directory
INNER JOIN
dbo.Category
ON
Directory.CategoryId = Category.CategoryId
LEFT OUTER JOIN
dbo.Location
ON
dbo.Directory.LocationId = location.Location_ID
) AS content
INNER JOIN
dbo.Directory
ON
content.DirectoryId = Directory.DirectoryId
WHERE
content.RowNo =1 and
(#locationUrlIdentifier or CategoryOrder = 1)
You can do it just in ONE query:
Select Query ...where ...
and ((#locationUrlIdentifier is null) or (CategoryOrder = 1))
You can use NULLIF instead of IS NULL
Refer : Check if a parameter is null or empty in a stored procedure
http://msdn.microsoft.com/en-us/library/ms177562.aspx
Alternatively you can use ISNULL() check and then change the null to empty string
IF (ISNULL(#locationUrlIdentifier,'') = '')
OR even before this check you can use ISNULL() to convert from NULL to empty string if it persists to be a problem