Setting a variable in T-SQL from a Query - tsql

So I have this query:
select ens_use_new_models_bit from cfo_transaction
inner join dbo.cfo_trans_entity_rel on te_tr_transaction_id=tr_transaction_id
inner join cfo_tran_quote on tq_tr_transaction_id = tr_transaction_id
left outer join cfo_engine_sponsor on ens_rs_sponsor_id = te_co_re_entity_id
where te_rv_rel_type_id=713 and tq_tran_quote_id = 3
It returns a bit value, which can also be NULL. I hardcoded 3 for testing but in reality another proc passes this value in, but that's not important here.
Now, in a stored proc, I need to set a variable that's declared in the proc:
SET #vRtn = NULL
as the string - either 'VBEngines' or 'WFModels', or keep it NULL if the bit from above returns NULL.
'VBEngines' if the bit is off, 'WFModels' if the bit is on.
Then after that, I need to perform a T-SQL condition on the value, to see if it's NULL or not. How would I do this? I'm so bad with SQL.
Thanks.

Assuming that you don't need the bit value itself stored in a variable as that was just a means to an end then this should do it.
select #vRtn = case ens_use_new_models_bit
when 0 then 'VBEngines'
when 1 then 'WFModels'
end /*Implicit Else NULL case*/
from cfo_transaction ...
In the case 0 rows are returned no assignment is made so #vRtn keeps its initial value,

declare #newmodelsbit bit, #vRtn varchar(10)
select #newmodelsbit = ens_use_new_models_bit from cfo_transaction
inner join dbo.cfo_trans_entity_rel on te_tr_transaction_id=tr_transaction_id
inner join cfo_tran_quote on tq_tr_transaction_id = tr_transaction_id
left outer join cfo_engine_sponsor on ens_rs_sponsor_id = te_co_re_entity_id
where te_rv_rel_type_id=713 and tq_tran_quote_id = 3
if #newmodelsbit is null
begin
set #vRtn = null
end
else
begin
if #newmodelsbit = 1 --bit is on
begin
set #vRtn = 'WFModels'
end
else -- bit is off
begin
set #vRtn = ' VBEngines'
end
end

Related

How to fix an expression of non-boolean type specified in a context where a condition is expected, near 'BEGIN'.?

Hey I have this query
IF (select kmkood from or_arved_read where kmkood = '1' or kmkood = '14' or kmkood = '15' or kmkood = '6' )
BEGIN
SET #stat_vat = 21
IF (select kmkood from or_arved_read where kmkood = '2' or kmkood = '7' )
SET #stat_vat = 12
But it returns An expression of non-boolean type specified in a context where a condition is expected, near 'BEGIN'.
how can i fix it?
Firstly, your IF doesn't have a boolean expression. The subquery returns a value (or more accurately for this scenario will return many and cause a different error) for the column kmkood, but then you don't do anything with that value. What value does that column need? The format should be something like this:
IF (SELECT SomeColumn FROM dbo.SomeTable WHERE... ) = 'SomeValue'
Also, if you have a BEGIN you need an END afterwards, which you don't have:
IF (SELECT SomeColumn FROM dbo.SomeTable WHERE... ) = 'SomeValue'
BEGIN
{Do several statements}
END
As, however, you are just doing a SET statement then you don't actually need the BEGIN and END statements.
I suspect what you are really after here, however, in an EXISTS:
IF EXISTS(SELECT 1 FROM dbo.or_arved_read WHERE kmkood IN (1,14,15,6))
SET #stat_vat = 21;
IF EXISTS(SELECT 1 FROM dbo.or_arved_read WHERE kmkood IN (2,7))
SET #stat_vat = 12;
You don't need all those ORs either, an IN works fine, and numbers shouldn't be in single quotes, so that makes things a bit shorter.

Exclude where clause based on function specification

I developed the following function:
create function kv_fn_ValuationPerItem_AW (#dDate date, #active bit)
returns table
as
return
(
select
Code ItemCode
, Description_1 ItemDescription
, ItemGroup
, Qty_On_Hand CurrentQtyOnHand
, AveUCst CurrentAvgCost
, Qty_On_Hand*AveUCst CurrentValue
from _bvSTTransactionsFull t
inner join StkItem s on t.AccountLink = s.StockLink
where ServiceItem = 0
and ItemActive = #active
and TxDate <= #dDate
group by Code, Description_1, ItemGroup, Qty_On_Hand, AveUCst
)
The function requires two parameters:
Date
Is the item Active - 1 = Active & 0 = Inactive
If I use the function as stipulated above, by specifying 1 for the Active Parameter, then the results will only be for Active Items.
If I specify 0, then it'll return all inactive Items.
How do I alter this function to cater for Active Items or both Active & Inactive?
i.e. if the parameter is 1, the where clause should read as ItemActive = #active, but when it's 0, the where clause should read as ItemActive in (1,0), How do I change the function to work like this?
I tried a case, but my syntax is not correct...
It's as simple as adding an or to your where cluase:
...
and (ItemActive = 1 OR #active = 0)
...
BTW, you might want to do it like this instead:
and (ItemActive = #active OR #active IS NULL)
which means that when you pass in 1 as #active you'll get only the active items, when you pass in 0 you'll get only the inactive members, but when you pass in null you'll get all records, regardless of the value in the ItemActive column.
Thanks Shnugo & Zohar for your answers,
Please amend your answers, then I'll mark yours as the answer.
The solution to my problem was to alter the Function as following:
create function kv_fn_ValuationPerItem_AW (#dDate date, #active bit)
returns table
as
return
(
select
Code ItemCode
, Description_1 ItemDescription
, ItemGroup
, Qty_On_Hand CurrentQtyOnHand
, AveUCst CurrentAvgCost
, Qty_On_Hand*AveUCst CurrentValue
from _bvSTTransactionsFull t
inner join StkItem s on t.AccountLink = s.StockLink
where ServiceItem = 0
and ItemActive in (1,#active)
and TxDate <= #dDate
group by Code, Description_1, ItemGroup, Qty_On_Hand, AveUCst
)
I think you are looking for this:
DECLARE #mockup TABLE(ID INT IDENTITY,SomeValue VARCHAR(100),Active BIT);
INSERT INTO #mockup VALUES('Row 1 is active',1)
,('Row 2 is active',1)
,('Row 3 is inactive',0)
,('Row 4 is inactive',0);
DECLARE #OnlyActive BIT=0; --set this to 1 to see active rows only
SELECT *
FROM #mockup m
WHERE (#OnlyActive=0 OR m.Active=1);
The idea is: If the parameter is set to 0 this expression is always true, if not, the column Active must be set to 1.
Hint: I used paranthesis, which was not needed in this simple case. But in your more complex WHERE clause they will be needed...
Hint2: I named the parameter OnlyActive, which expresses a bit better what you are looking for. You might turn the parameter to ShowAll with an invers logic too...

tsql : Access query to TSQL union update conversion correct?

I have a query in access which i need to convert to a stored proc in sql server 2005.
the query in access is as follows:
UPDATE
tblitem,
tblFileSignature
SET
tblitem.strFileProcesstype = [tblFileSignature].[STRFILEPROCESSTYPE], tblitem.strFileSignatureType = [tblFileSignature].[strfilesignaturetype]
WHERE
(((tblitem.strFileSignatureType) Is Null) AND
((tblitem.strFileExclude)="n") AND
((InStr([tblitem].[strfilesignature],[tblFileSignature].[strsignature]))=1) AND ((tblitem.uidItemType)=1 Or (tblitem.uidItemType)=5) AND
((tblitem.uidCollection)=[forms]![frmSetup]![txtInputCol]) AND ((tblitem.strFileSignature) Not Like "d0c*") AND
((tblFileSignature.strFileProcessType) Not Like "ZIP"));
in tsql.. would this be the same?
update tblItem
set
i.strFileProcesstype = f.strFileProcesstype,
i.strFileSignatureType = f.strfilesignaturetype
from tblItem as I UNION tblFileSignature as F
WHERE (((i.strFileSignatureType) Is Null) AND
((i.strFileExclude)="n") AND
((i.[strfilesignature] like F.strsignature)) AND
((i.uidItemType)=1 Or
(i.uidItemType)=5) AND
((i.uidCollection)=#inputcolumn AND
((i.strFileSignature) Not Like 'd0c%') AND
((F.strFileProcessType) Not Like 'ZIP'));
thanks in advance
UPDATE:
so i'm going with the following. if i uncomment the declare and select clause and just execute from the declare down, it runs, if i comment the declare and select parts, it says error near ';'.
UPDATE I
SET
I.strFileProcesstype = F.STRFILEPROCESSTYPE,
I.strFileSignatureType = F.strfilesignaturetype
--declare #uidcollectionID int
--select I.strFileSignatureType
from
tblItem I
inner join tblFileSignature F
on
I.strfilesignature = left(F.strsignature,len(I.strfilesignature))
WHERE I.strFileSignatureType Is Null
AND I.strFileExclude='n'
AND I.uidItemType in (1,5)
AND I.uidCollection = #uidCollectionID
AND left(I.strFileSignature,3) <> 'd0c'
AND F.strFileProcessType <> 'ZIP';
any ideas?
You should change the
Double Quotes to Single Quotes
* to %
Replace the InStr with LIKE
Other than that, it looks fine to me.
No, you'd use a JOIN, not a UNION.
You can either make it a CROSS JOIN, and continue to apply the join conditions in the WHERE clause, or you can make it an inner join:
from tblItem as I INNER JOIN tblFileSignature as F
ON ((InStr(i.[strfilesignature],F.[strsignature]))=1)
And remove that condition from the WHERE clause (Lieven's answer also applies).
This should be close to what you need. May need to work on the join condition, but I think my conversion from INSTR will do it.
UPDATE i
SET strFileProcesstype = fs.STRFILEPROCESSTYPE,
strFileSignatureType = fs.strfilesignaturetype
FROM tblitem i
INNER JOIN tblFileSignature fs
ON i.strfilesignature = LEFT(fs.strsignature, LEN(i.strfilesignature))
WHERE i.strFileSignatureType IS Null
AND i.strFileExclude='n'
AND i.uidItemType IN (1,5)
AND i.uidCollection = #inputcolumn
AND LEFT(i.strFileSignature,3) <> 'd0c'
AND fs.strFileProcessType <> 'ZIP';

How do I use T-SQL's Case/When?

I have a huge query which uses case/when often. Now I have this SQL here, which does not work.
(select case when xyz.something = 1
then
'SOMETEXT'
else
(select case when xyz.somethingelse = 1)
then
'SOMEOTHERTEXT'
end)
(select case when xyz.somethingelseagain = 2)
then
'SOMEOTHERTEXTGOESHERE'
end)
end) [ColumnName],
Whats causing trouble is xyz.somethingelseagain = 2, it says it could not bind that expression. xyz is some alias for a table which is joined further down in the query. Whats wrong here? Removing one of the 2 case/whens corrects that, but I need both of them, probably even more cases.
SELECT
CASE
WHEN xyz.something = 1 THEN 'SOMETEXT'
WHEN xyz.somethingelse = 1 THEN 'SOMEOTHERTEXT'
WHEN xyz.somethingelseagain = 2 THEN 'SOMEOTHERTEXTGOESHERE'
ELSE 'SOMETHING UNKNOWN'
END AS ColumnName;
As soon as a WHEN statement is true the break is implicit.
You will have to concider which WHEN Expression is the most likely to happen. If you put that WHEN at the end of a long list of WHEN statements, your sql is likely to be slower. So put it up front as the first.
More information here: break in case statement in T-SQL
declare #n int = 7,
#m int = 3;
select
case
when #n = 1 then
'SOMETEXT'
else
case
when #m = 1 then
'SOMEOTHERTEXT'
when #m = 2 then
'SOMEOTHERTEXTGOESHERE'
end
end as col1
-- n=1 => returns SOMETEXT regardless of #m
-- n=2 and m=1 => returns SOMEOTHERTEXT
-- n=2 and m=2 => returns SOMEOTHERTEXTGOESHERE
-- n=2 and m>2 => returns null (no else defined for inner case)
If logical test is against a single column then you could use something like
USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
More information - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017

T-SQL Delete command basing on table variable

I need to delete some rows from table where indexes are equal indexes in table variable
declare #m_table as table
(
number NUMERIC(18,0)
)
...
inserting some rows into #m_table
...
DELETE ct FROM [dbo].[customer_task] ct
inner join project_customer pc on pc.id_customer = #m_table.number
inner join customer_user cu on cu.id_project_customer = pc.id
WHERE ct.id_csr_user = cu.id AND ct.id_status = 1;
but this code generates an error: Must declare the scalar variable "#m_table" How to solve that ?
You probably have a 'GO' (a batch separator) in those '...'
Variable declarations do not span batches.
The error means that SQL is expecting you to treat #m_table like a standard table, rather than a scalar (int, bit, etc.) variable. Perhaps something like this will work?
DELETE ct FROM [dbo].[customer_task] ct
WHERE ct.id_csr_user IN (
SELECT cu.id FROM customer_user cu
INNER JOIN project_customer pc ON pc.id = cu.id_project_customer
WHERE pc.id_customer IN (SELECT number FROM #m_table.number)
) AND ct.id_status = 1;