Setting a variable using a stored procedure without printing an output - sql-server

I have a stored procedure as follows which returns a value:
DECLARE #outputValue decimal(18,10)
set #outputValue = (
select TOP 1 TotalUsageFactor as '801 UNR Usage Factor'
from MarketMessage as a
inner join messagetype591 as b on a.MarketMessageID = b.MarketMessageID
inner join AdditionalAggregationInformation as c on b.MessageType591ID = c.MessageType591ID
inner join AdditionalAggregationData as d on c.AdditionalAggregationInformationID = d.AdditionalAggregationInformationID
where SettlementRunIndicator = 20
and LoadProfileCode = 801
and TimeOfUse = 'UNR'
order by SettlementDate desc)
RETURN #outputValue
Despite this being a decimal value I seem to always be only able to return an int, this is used within another parent stored procedure and is called as follows:
DECLARE #UsageFactor801UNR decimal(18,10)
EXEC #UsageFactor801UNR = GetLatestUsageFactor801UNR
If I do it this way there is no output value being returned and at the end of the query I am being returned the final table of data as expected. If I however change the code to the following:
select TOP 1 TotalUsageFactor as '801 UNR Usage Factor'
from MarketMessage as a
inner join messagetype591 as b on a.MarketMessageID = b.MarketMessageID
inner join AdditionalAggregationInformation as c on b.MessageType591ID = c.MessageType591ID
inner join AdditionalAggregationData as d on c.AdditionalAggregationInformationID = d.AdditionalAggregationInformationID
where SettlementRunIndicator = 20
and LoadProfileCode = 801
and TimeOfUse = 'UNR'
order by SettlementDate desc
RETURN
I am now able to retrieve the correct decimal value but in my parent query I am returning these values before returning the table of information that I actually require, how can I have it so that I am able to return a decimal value from the function with no output or have it so that there is no return from the execution of the query within the parent

Related

Query works as expected, SSRS finds error?

This question was closed because someone thought it was the same issue as SSRS multi-value parameter using a stored procedure
But it is not. My report is not a stored procedure and thus, behaves differently. Also, this issue describes a result of getting no results if multi-valued params are used and that too is inaccurate for this scenario. So I'll try posting this again.
My report for the most part works. It is when I select more than one value from either of 2 specific params (#global, #manual) that I get this error:
Here is the SQL:
DECLARE #STATE VARCHAR(2) = 'mn'
,#START DATE = '6/1/2020'
,#END DATE = '7/1/2020'
,#GLOBAL VARCHAR(50) = 'indigent fee'
,#MANUAL VARCHAR(100) = '''misc charges'',''discount'''
DROP TABLE
IF EXISTS #customers
,#test
SELECT DISTINCT ch.amount
,ch.vehicle_program_id
,c.customer_id
,ch.customer_charge_id
,ch.charge_type
INTO #customers
FROM customer c
JOIN customer_charge ch(NOLOCK) ON c.customer_id = ch.customer_id
JOIN service_history sh(NOLOCK) ON sh.customer_id = c.customer_id
JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
WHERE ch.entry_date BETWEEN #START
AND #END
AND ch.price_trigger_id IN (
16
,15
)
AND ch.source_type = 1
AND sh.service_type = 5
AND h.is_duplicate = 0;
WITH CTE_global
AS (
SELECT DISTINCT ch.charge_type
,'global' AS type
FROM customer_charge ch
JOIN store s ON ch.store_id = s.store_id
JOIN address a ON a.id = s.address_id
JOIN locality l ON a.locality_id = l.id
WHERE l.region = #state
AND ch.price_trigger_id = 16
UNION ALL
SELECT 'None'
,'global'
)
,CTE_manual
AS (
SELECT DISTINCT ch.charge_type
,'manual' AS type
FROM customer_charge ch
JOIN store s ON ch.store_id = s.store_id
JOIN address a ON a.id = s.address_id
JOIN locality l ON a.locality_id = l.id
WHERE l.region = #state
AND ch.price_trigger_id = 15
UNION ALL
SELECT 'None'
,'manual'
)
SELECT DISTINCT c.last_name
,c.first_name
,vp.account_no
,cust.charge_type
,cust.amount
,sh.service_date
,s.store_name_short
,GLOBAL = g.charge_type
,manual = m.charge_type
INTO #test
FROM vehicle_program vp(NOLOCK)
JOIN vehicle v(NOLOCK) ON v.vehicle_id = vp.vehicle_id
JOIN service_history sh(NOLOCK) ON sh.vehicle_program_id = vp.program_id
AND service_type = 5
JOIN customer c(NOLOCK) ON v.customer_id = c.customer_id
AND c.customer_id = sh.customer_id
JOIN store s(NOLOCK) ON vp.current_store_id = s.store_id
JOIN #customers cust ON cust.customer_id = c.customer_id
AND cust.vehicle_program_id = sh.vehicle_program_id
JOIN customer_condition cc(NOLOCK) ON c.customer_id = cc.customer_id
JOIN customer_charge ch(NOLOCK) ON ch.customer_id = c.customer_id
JOIN service_charge sc ON sc.service_history_id = sh.service_history_id
AND sc.customer_charge_id = cust.customer_charge_id
JOIN header h(NOLOCK) ON h.service_history_id = sh.service_history_id
JOIN CTE_global g ON g.charge_type = ch.charge_type
JOIN CTE_manual m ON m.charge_type = ch.charge_type
WHERE cc.state_of_conviction = #state
AND sh.service_date BETWEEN #START
AND #END
AND h.is_duplicate = 0
SELECT *
FROM #test
WHERE GLOBAL IN (
CASE
WHEN #global IN ('None')
THEN charge_type
WHEN #global NOT IN ('None')
THEN #global
END
)
OR manual IN (
CASE
WHEN #manual IN ('None')
THEN charge_type
WHEN #manual NOT IN ('None')
THEN #manual
END
)
For clarity, the last bit in the query there is some logic to allow for these two params to be optional: so by selecting 'None' that param is rendered useless basically. It seems clear that the issue is with this last bit, specifically my WHERE clause using the CASE expression. When I remove that, I don't get the error, but I of course lose my logic. What's most confusing is that the error indicates an issue with a comma, but there's no comma in that part of the SQL?? Any help is going to be greatly appreciated.
Assuming users will only select 'None' from the list on it's own and never with another value then the following should work.
WHERE (GLOBAL IN (#Global) OR #Global = 'None')
AND
(manual IN (#manual) OR #manual = 'None')
this question was closed because someone thought it was the same issue
It is a dupe, but you kind of have to read between the lines in the other answers to apply it to this scenario. The point is that SSRS replaces multi-select parameters with delimited strings in the query body itself, and this transformation can lead either to unexpectedly getting no results, or in an illegal SQL query, depending on where the parameter marker appears in the original query.
I'll make it a bit clearer exactly what's going on. You can repro this behavior with this as your Data Set query:
drop table if exists #foo
create table #foo(charge_type varchar(200) , global varchar(200))
select *
from #foo
WHERE GLOBAL IN (
CASE
WHEN #global IN ('None')
THEN charge_type
WHEN #global NOT IN ('None')
THEN #global
END
)
And configure #global as a parameter that allows multi-select. When the user selects multiple values SSRS transforms the query into:
drop table if exists #foo
create table #foo(charge_type varchar(200) , global varchar(200))
select *
from #foo
WHERE GLOBAL IN (
CASE
WHEN N'a',N'b' IN ('None')
THEN charge_type
WHEN N'a',N'b' NOT IN ('None')
THEN N'a',N'b'
END
)
Which fails with An expression of non-boolean type specified in a context where a condition is expected, near ','.

Stored Procedure - How to Ignore a Join when #packageType = 1

I want to change the left join to inner join, but for me to do that,
I want the PACKAGEDETAILS.MenuID = MENU.ID join to happen only if the #packageType = 2, else I want my stored procedure to ignore the join
I am new to stored procedures and SQL, I tried using case when, but I failed, I tried if then, still didn't achieve what I wanted.
set #slot = 5;
set #numberofattendees = 100;
set #foodtype = 0;
set #packagetype = 1;
select * FROM PROPERTY
JOIN PACKAGEDETAILS ON PACKAGEDETAILS.ID =
(SELECT
PACKAGEDETAILS.ID
FROM
PACKAGEDETAILS
`````````````````````````````````````````````````````
LEFT JOIN MENU ON PACKAGEDETAILS.MenuID = MENU.ID AND -- i want this join to happen only if the #packageType = 2
MENU.IsActive = 1 AND
MENU.IsDeleted = 0 AND
(MENU.FoodTypeID = 0 OR #FoodType = 0)
`````````````````````````````````````````````````````
JOIN PACKAGEAPPLICABILITY ON PACKAGEDETAILS.ID = PACKAGEAPPLICABILITY.packagedetailsid
WHERE
PACKAGEAPPLICABILITY.IsActive = 1 AND
PACKAGEAPPLICABILITY.IsDeleted = 0
ORDER BY
PACKAGEDETAILS.CostPrice ASC LIMIT 1
)
Since there wont be any menu for packageType 1, I want my stored procedure to ignore the join if #packageType = 1 and only work when #packageType = 2.
You are trying to pack 2 different queries into 1. In general, that is not a good idea in SQL, as it makes the query optimizer work much harder. You will be better off with either writing 2 separate procedures, or within the same procedure, write 2 separate queries and use IF conditional execution to decide which query to execute:
IF Packagetype = 2
select * FROM PROPERTY
JOIN PACKAGEDETAILS ON PACKAGEDETAILS.ID =
(SELECT
PACKAGEDETAILS.ID
FROM
PACKAGEDETAILS
`````````````````````````````````````````````````````
LEFT JOIN MENU ON PACKAGEDETAILS.MenuID = MENU.ID AND -- i want this join to happen only if the #packageType = 2
MENU.IsActive = 1 AND
MENU.IsDeleted = 0 AND
(MENU.FoodTypeID = 0 OR #FoodType = 0)
`````````````````````````````````````````````````````
JOIN PACKAGEAPPLICABILITY ON PACKAGEDETAILS.ID = PACKAGEAPPLICABILITY.packagedetailsid
WHERE
PACKAGEAPPLICABILITY.IsActive = 1 AND
PACKAGEAPPLICABILITY.IsDeleted = 0
ORDER BY
PACKAGEDETAILS.CostPrice ASC LIMIT 1
)
ELSE
select * FROM PROPERTY
JOIN PACKAGEDETAILS ON PACKAGEDETAILS.ID =
(SELECT
PACKAGEDETAILS.ID
FROM
PACKAGEDETAILS
JOIN PACKAGEAPPLICABILITY ON PACKAGEDETAILS.ID = PACKAGEAPPLICABILITY.packagedetailsid
WHERE
PACKAGEAPPLICABILITY.IsActive = 1 AND
PACKAGEAPPLICABILITY.IsDeleted = 0
ORDER BY
PACKAGEDETAILS.CostPrice ASC LIMIT 1
)
Define a variable and construct your query by setting the variable according to your conditions. When you create the query execute it with exec command.
Here is an example.

Instantiating temp table based on the result of joins after creating a new variable

I am trying to store the result of a query as a temp table in SQL Server. Can someone explain why the set syntax is wrong here? I thought I followed for format from here correctly.
select *
into #temp_Academic
set XlistGrp_Course_CRN = s.Subject+' '+s.Course_Number+' ('+x.XlistGrp_Course_CRN+')'
from AcademicYear r
inner join Xlist x on r.XlistGrp = x.xlistgrp and r.term=x.term
inner join Sections s on x.term = s.Term and x.XlistGrp_Course_CRN = s.CRN
Error:
Msg 102, Level 15, State 1, Line 21
Incorrect syntax near '='.
That set is for assigning the variable, and I assume you have a typo, missing , in your post. and generally speaking you should not have both select, set in one selecting clause.
What you are looking for is just alias the column, you can try:
select *,XlistGrp_Course_CRN = s.Subject+' '+s.Course_Number+' ('+x.XlistGrp_Course_CRN+')'
into #temp_Academic,
from AcademicYear r
inner join Xlist x on r.XlistGrp = x.xlistgrp and r.term=x.term
inner join Sections s on x.term = s.Term and x.XlistGrp_Course_CRN = s.CRN
OR
select *,s.Subject+' '+s.Course_Number+' ('+x.XlistGrp_Course_CRN+')' as XlistGrp_Course_CRN
into #temp_Academic,
from AcademicYear r
inner join Xlist x on r.XlistGrp = x.xlistgrp and r.term=x.term
inner join Sections s on x.term = s.Term and x.XlistGrp_Course_CRN = s.CRN
For your reference post, the op's question is how to assign the result from a query to one variable instead giving value directly.
Compare:
SELECT #varble = value FROM TABLE -- assume only one value returned
VS
SET #varable = 5 --assume you declared #varable as INT
declare #CListGrp as nvarchar(255)
select *, #XlistGrp_Course_CRN = s.Subject+' '+s.Course_Number+' ('+x.XlistGrp_Course_CRN+')' into #temp_Academic
from AcademicYear r
inner join Xlist x on r.XlistGrp = x.xlistgrp and r.term=x.term
inner join Sections s on x.term = s.Term and x.XlistGrp_Course_CRN = s.CRN

Stored Procedure If / Then Statement

We are trying to implement a password interval, if there is one.
If sm_Setting(PasswordExpireDays) has a value, we use it. If not, continue on
CREATE Procedure user_password_date_interval_check
#ua_pk uniqueidentifier
AS
DECLARE #PasswordExpireDays int
SET #PasswordExpireDays = 0
SELECT
sm_Setting, sm_Value
FROM
Setting_Misc AS sm
INNER JOIN
Syndicates As syn ON sm.syn_fk = syn.syn_pk
INNER JOIN
Company As c ON c.syn_fk = syn.syn_pk
INNER JOIN
User_Accounts As ua ON ua.c_fk = c.c_pk
WHERE
sm.sm_Setting = 'PasswordExpireDays'
THEN sm.sm_Value = #PasswordExpireDays
I'm having issues with the WHERE clause. I have tried CASE. Bottom line is, this row (based on a PK and Setting), I want to grab the value from the Value column.
CREATE Procedure user_password_date_interval_check
#ua_pk uniqueidentifier
AS
DECLARE #PasswordExpireDays int
SELECT
--sm_Setting,
#PasswordExpireDays =COALESCE(sm_Value,0)
FROM
Setting_Misc AS sm
INNER JOIN
Syndicates As syn
ON sm.syn_fk = syn.syn_pk
INNER JOIN
Company As c
ON c.syn_fk = syn.syn_pk
INNER JOIN
User_Accounts As ua
ON ua.c_fk = c.c_pk
WHERE sm.sm_Setting = 'PasswordExpireDays'
--#PasswordExpireDays is either default 0 or the value from the table if not null.

Get value from the select statement on the row above in T-SQL

I want to get the value the previous select statement returned (similar to the ##IDENTITY function)
Code:
IF EXISTS (SELECT MyCriticalValue
FROM Units u
JOIN pUnit pu
ON pu.UnitID = u.UnitID
WHERE u.ChildUnitID = ( SELECT ps.UnitID
FROM psUnit ps
WHERE ps.Code = #CurrentCode)
AND pu.Type = 117
AND u.TypeID = 1 )
BEGIN
SET #CriticalValue = ##identity
END
I know that ##IDENTITY doesn't work since that's only for inserts. Is there a similar function to achieve what I want (which is to get "MyCriticalValue" from the select statement into the variable #CriticalValue without typing the entire SELECT statement twice).
EDIT:
Clarification: When I come to this point in my SQL script #CriticalValue is already set and I should ONLY overwrite it if the select-statement returns anything, so it should not be overwritten in any other case.
SELECT #CriticalValue = ISNULL(MyCriticalValue, #CriticalValue)
FROM Units u
JOIN pUnit pu
ON pu.UnitID = u.UnitID
WHERE u.ChildUnitID = (
SELECT ps.UnitID
FROM psUnit ps
WHERE ps.Code = #CurrentCode
)
AND pu.Type = 117
AND u.TypeID = 1;
IF #CriticalValue IS NOT NULL
...
I assumed that your query return one value.

Resources