How to pass dynamic View name in SQL stored procedure without using a dynamic query? - sql

Here is my stored procedure below. I am concatenating #CultureCode paramter along with view name which is [_0002HR_EmployeeNames_en-US_View]. The part en-US will be passed through a parameter named as #CultureCode. Is there any way to do so because i have requirement not to use dynamic query. Thank you.
CREATE PROCEDURE [dbo].[_001HR_Report_Loans] (#Parameters VARCHAR(max))
AS
DECLARE #ReportOption VARCHAR(5) SET #ReportOption = [dbo].DB_Split(#Parameters, 1)
DECLARE #CultureCode VARCHAR(10) SET #CultureCode = [dbo].DB_Split(#Parameters, 2)
DECLARE #ShowItems VARCHAR(5) SET #ShowItems = [dbo].DB_Split(#Parameters, 3)
DECLARE #StartDate NVARCHAR(8) SET #StartDate = [dbo].DB_Split(#Parameters, 4)
DECLARE #EndDate NVARCHAR(8) SET #EndDate = [dbo].DB_Split(#Parameters, 5)
DECLARE #EmployeeCode NVARCHAR(30) SET #EmployeeCode = [dbo].DB_Split(#Parameters, 6)
DECLARE #BranchCode NVARCHAR(30) SET #BranchCode = [dbo].DB_Split(#Parameters, 7)
--IF #StartDate = ''
-- SET #StartDate = NULL
SELECT HR.*, EN.[Name] AS EmployeeName
FROM [0002HR_EmployeeLoans] HR
LEFT JOIN [_0002HR_EmployeeNames_ + '#CultureCode' +_View] EN ON HR.EmployeeCode = EN.EmployeeCode
LEFT JOIN [_0002HR_EmployeePackagesView] EP ON EP.EmployeeCode = HR.EmployeeCode
WHERE
(HR.EmployeeCode = #EmployeeCode OR #EmployeeCode IS NULL)
AND
(EP.BranchCode = #BranchCode OR #BranchCode IS NULL)
AND
(HR.Date BETWEEN #StartDate AND #EndDate OR #StartDate IS NULL AND #EndDate IS NULL)
AND
(HR.Date >= #StartDate OR #StartDate IS NULL)
AND
(HR.Date <= #EndDate OR #EndDate IS NULL)

This is not possible in T-SQL so far. Things like TOP clauses, table or column names can not be parameterized.
One way would be to create a union over all possible tables/views, add a new column that matches the table/view name and filter that.
Like this:
SELECT * FROM
(
SELECT 'Table1' as TableName, t1.* FROM Table1 t1 WHERE ...
UNION ALL
SELECT 'Table2' as TableName, t2.* FROM Table2 t2 WHERE ...
) tmp
WHERE TableName = #tableName
Another (and possibly the most "clean" way) would be to only have one single table and make the culture a column in that table, so you only need to pass the correct culture string to filter over that column.

So you have a view per language. They are getting the data from the tables for their particular language. But now you want to write a procedure that is not language-specific.
The solution seems simple: Don't use the language views, but access the tables directly instead. (Or build an all-languages view which you query with where language = #language.)

Related

Assigning variables to use in query

I am moving from Oracle to SQL Server and I am noticing differences regarding assigning variables in a query. I wonder if someone could write me a simple example of how I can do this in SSMS please?
In the example below I am looking to assign the variable #date1 at the beginning of the select statement so that I can simply change the date at the top instead of having to change it several times in the query where #date1 is used several times.
SELECT *
FROM table
where date = #date1
Thanks
Based on your example the syntax would be as follows:
DECLARE #date1 DATETIME
SET #date1 = '2017-01-01 00:00:00.000'
Then reference #date1 in your query as you have above.
More broadly, the syntax is:
DECLARE #<name of variable> <type>
SET #<name of variable> = <value>
-- Simple declares
DECLARE #Variable1 VARCHAR(100)
DECLARE #Variable2 DATE
DECLARE #VariableTable TABLE (
numberColumnName INT,
textColumnName VARCHAR(MAX))
-- Chained declares
DECLARE
#Variable3 VARCHAR(100),
#Variable4 INT
-- Declare with initiation
DECLARE #Variable5 INT = 150
DECLARE #Variable6 DATE = '2018-05-05' -- Implicit conversion (varchar to date)
DECLARE #Variable7 FLOAT = 1945.15 * 1648.12 / #Variable5 -- Expressions can be used
DECLARE #Variable8 INT = (SELECT COUNT(1) FROM sys.objects)
-- Chained declares with initiation
DECLARE
#Variable9 VARCHAR(100) = 'Afla',
#Variable10 INT = 9164 * #Variable5
-- Change variable values (without declaring)
SET #Variable1 = 'Some value'
SET #Variable2 = CONVERT(DATE, GETDATE())
For your example:
DECLARE #DateFilter DATE = '2018-05-16' -- Use ISO standard date format (yyyy-MM-dd) when you hard-code them as literals
SELECT
*
FROM
YourTable AS T
WHERE
T.DateToFilter >= #DateFilter
DECLARE #date1 DATE = '2018-04-11'
This code may be fine, but be aware of dates formats :date (Transact-SQL)
and the need of using either Date, Datetime, or Datetime2.

How do I include optional parameters using IF-THEN-ELSE logic in a SQL query?

Here is the create statement for a stored procedure:
Create Procedure SearchCreatedAssignments
(#LessonName Varchar(50), #DateFrom date, #DateTo Date, #LocationCode Varchar(10))
As
BEGIN
Basically, I want to write a query that searches the database based on the values of the parameters. For example:
Select *
from dbo.test
where (LessonName = #LessonName)
AND (StartDate = #DateFrom)
AND (EndDate = #DateTo)
AND (LocationCode = #LocationCode)
Fairly simple, right? However, if any of these parameters are null (or contain an empty string), I would like to omit them from the search, and search by only the parameters that are not null. I was thinking something like this:
--if #LocationCode is null OR #LocationCode = '' -> omit #LocationCode from the search
This is obviously pseudo code. How can I do this? Forgive me if this is a simple task; I am new to SQL.
Consider the following. If a parameter is NULL or empty, the default value will be the field in question
Select *
from dbo.test
where LessonName = IsNull(NullIf(#LessonName,''),LessonName)
AND StartDate = IsNull(NullIf(#DateFrom,''),StartDate)
AND EndDate = IsNull(NullIf(#DateTo,''),EndDate)
AND LocationCode = IsNull(NullIf(#LocationCode,''),LocationCode)
You can either write a dynamic SQL statement and execute it using sp_ExecuteSQL in your procedure, or you can get tricky with the SQL like:
Select *
from dbo.test
where (LessonName = #LessonName)
AND (StartDate = #DateFrom)
AND (EndDate = #DateTo)
AND (LocationCode = #LocationCode or #LocationCode IS NULL or #LocationCode = '')
You can use the COALESCE function to do so in this way:
where LessonName = coalesce(#LessonName, LessonName)
AND StartDate = coalesce(#DateFrom, StartDate)
AND EndDate = coalesce(#DateTo, EndDate)
AND LocationCode = coaleasce(#LocationCode, LocationCode)
Although I'm not sure about the empty strings. It will work for null values, in other databases coalesce also handle the empty strings. If it do not work you can use case in the same manner:
LessonName = case when #LessonName is not null and #LessonName != ''
then #LessonName else LessonName end
And just use the same logic for the other parameters.
INHO on this case a good way is using a dynamic query.
DECLARE #cmd VARCHAR(MAX);
SET #CMD = 'SELECT * FROM dbo.Text WHERE #Param1 = 'x''; --at least on parameter
IF #PARAM2 IS NOT NULL
BEGIN
SET #CMD = #CMD + ' AND Param2 = #Param2'
END
IF #PARAM3 IS NOT NULL
BEGIN
SET #CMD = #CMD + ' AND Param3 = #Param3'
END
EXECUTE (#CMD);

ssrs Ignoring variable which is not declared

This is my part of the query which i am using in the Dataset in SSRS2008
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime = (SELECT TOP 1 StartDate FROM UserManagerDates WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #StartDate = #NewStartDate;
END
Question:
I was copying my query into dataset from ssms and when i hit refresh in dataset i only get prompted for #a and #b in define query parameters. Actually i wasn't even declaring #startdate so i was expecting #startdate variable in define query parameters tab. What changes should i make to to get prompted for #startdate along with the other two variables?
You are setting the #startdate parameter, it is supposed to be populated by SSRS instead of your query, that could be the reason you are not being prompted.
I think you want to use #startdate to populate #NewStartDate, if so try this:
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime =
(SELECT TOP 1 StartDate FROM UserManagerDates
WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #NewStartDate = #startdate;
END

T-SQL Dynamic variable insert

can some one help, with this query. I have 10 rows in my temp table
Declare #date date = '2014-11-01'
Declare #iDate int = '20141101'
Create table #test33(Paname varchar(100))
insert into #test33
Go
Now i have 10 rows in temp table. I want to insert those temp values in my cte dynamically
Declare #StartDate date = '2014-11-01'
Declare #EndDate date = '2014-11-30'
Declare #Paname nvarchar(100) = 'MPU' --- i have multiple panames how can i insert dyamically in cte or any other solution?
;with pla as
( SELECT*
FROM [dbo].[Pla] pl
JOIN dbo.testplan cl
ON pl.ClientId = cl.ClientId
where pl.name = #Paname
and pl.StartDate >= #StartDate and pl.EndDate <= #EndDate
)
select * from pla
You can loop throw multiple parameters using WHILE or using CURSOR. Inside it you can used dynamic sql:
declare #DSQL varchar(MAX)
SET #DSQL = ';with pla as
( SELECT*
FROM [dbo].[Pla] pl
JOIN dbo.testplan cl
ON pl.ClientId = cl.ClientId
where pl.name = '+#Paname+'
and pl.StartDate >= '+#StartDate+' and pl.EndDate <= '+#EndDate+'
)
select * from pla'
EXEC(#DSQL)

SQL Stored Procedure set variables using SELECT

I have a stored procedure in SQL Server 2005 with multiple variables and I want to set the values of these variables using a select statement. All three variables come from a same table and there should be a way to set them using one select statement instead of the way I currently have as shown below. Please help me to figure it out.
DECLARE #currentTerm nvarchar(max)
DECLARE #termID int
DECLARE #endDate datetime
SET #currentTerm =
(
Select CurrentTerm from table1 where IsCurrent = 1
)
SET #termID =
(
Select TermID from table1 where IsCurrent = 1
)
SET #endDate =
(
Select EndDate from table1 where IsCurrent = 1
)
select #currentTerm = CurrentTerm, #termID = TermID, #endDate = EndDate
from table1
where IsCurrent = 1
One advantage your current approach does have is that it will raise an error if multiple rows are returned by the predicate. To reproduce that you can use.
SELECT #currentTerm = currentterm,
#termID = termid,
#endDate = enddate
FROM table1
WHERE iscurrent = 1
IF( ##ROWCOUNT <> 1 )
BEGIN
RAISERROR ('Unexpected number of matching rows',
16,
1)
RETURN
END