Modifying a SQL query within the Select statement - tsql

I have a stored proc that is called from my asp.net page. The field "RecordUpdated" returns TRUE or FALSE. I need that column to return YES (if true) or NO (if false)
How would I do that?
SET #SQL = 'SELECT RecID, Vendor_Number, Vendor_Name, Invoice_Number, Item_Number, RecordAddDate, RecordUpdated FROM Vendor_Invoice_Log'
SET #SQL = #SQL + ' ORDER BY Item_Number, Vendor_Number
PRINT #SQL

If all you are doing is trying to change TRUE to YES and FALSE to NO, you can do this:
select case
when recordupdated = true then 'YES'
when recordupdated = false then 'NO'
end recordupdates ...
Of course your code doesn't actually execute, so I am uncertain why you showed lines 2 and 3.

In situations where you need to return one or the other of something when doing a SELECT, the
CASE
WHEN true
THEN YES
WHEN false
THEN NO
END AS RecordUpdated
is pretty useful.

Sounds like a job for CASE()...

Related

How to assign variable if Cursor returns Bit of 0

I have written a cursor to search through a table looking at one bit value.
If all values are 1, I send an email. But if one value is 0 in any row, I don't send the email. The issue that I am having comes in my If statement. In SSMS, "#isComplete = 0" is breaking with only an "Incorrect syntax" error. I am not sure what I am missing here. My code is below. Thank you.
-------------------------------------------------
-- Start the INNER Cursor --
-------------------------------------------------
DECLARE #Complete int
DECLARE #isComplete Bit = 1
DECLARE INNERCur CURSOR FOR
SELECT Complete
FROM #AAEAPVS
OPEN INNERCur
FETCH NEXT FROM INNERCur INTO #Complete
WHILE ##FETCH_STATUS = 0
BEGIN
If #Complete = 0
BEGIN
#isComplete = 0
END
FETCH NEXT FROM INNERCur INTO #Complete
END
CLOSE InnerCurs
DEALLOCATE InnerCurs
-------------------------------------------------
-- INNER Curser END --
-------------------------------------------------
The incorrect syntax is that you need to use SET to assign the variable value, so change
#isComplete = 0
to
SET #isComplete = 0
And assuming you want to exit as soon as you find something that is not complete you should change your WHILE condition to
WHILE ##FETCH_STATUS = 0 AND #isComplete = 1
But most important of all, you probably don't need to use a cursor at all - you should avoid cursors in SQL if possible. You can probably just do something like this
DECLARE #isComplete Bit = 1
IF EXISTS (SELECT * FROM #AAEAPVS WHERE Complete = 0)
BEGIN
SET #isComplete = 0
END
and even that is more than you need, you can do it in a single statement
DECLARE #isComplete Bit = 1
SELECT #isComplete = 0 FROM #AAEAPVS WHERE Complete = 0
The syntax error results from not having a statement on the line. You need to use either SET or SELECT to assign a value to a variable, e.g. set #isComplete = 0.
Why, pray tell, a cursor rather than a simple EXISTS query? A far more efficient solution is:
select #isComplete = case
when exists ( select 42 from #AAEAPVS where Complete = 0 ) then 0
else 1 end;
Tip: It is helpful to tag database questions with both the appropriate software (MySQL, Oracle, DB2, ...) and version, e.g. sql-server-2014. Differences in syntax and features often affect the answers.

Check if a full text catalog exists in 2000

I'm trying to detect whether a database has a specific full text catalog so that I can either use it or avoid executing part of a script that would create errors without the catalog. I know in sql server 2005 you can use:
IF EXISTS(SELECT 1 FROM sys.fulltext_catalogs WHERE name = 'catalog_name')
But we have to support sql server 2000 still and I can't use that. Is there another way to check for the catalog?
The ##version check might need altering, but this should work:
declare #catalogExists tinyint
set #catalogExists = 0
if (##version like ('%SQL%Server%2000%')) begin
if exists(SELECT 1 FROM [master].[dbo].[sysfulltextcatalogs] WHERE name = 'catalog_name')
set #catalogExists = 1
end
else begin
IF EXISTS(SELECT 1 FROM sys.fulltext_catalogs WHERE name = 'catalog_name')
set #catalogExists = 1
end
print #catalogExists

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

Is DECLARE what I should be using in order to reference a created field within the same program

I'm trying to create a new field and then later on in my program reference that new field within a case statement, but I can't seem to get the syntax right - my error message says there's an error near the '='.
Here's my code:
declare #source_sys_obligation_id varchar(40);
if facility_utilization in ('F')
set source_sys_obligation_id = source_sys_facility_id
else set source_sys_obligation_id = source_sys_utilization_num;
select
source_sys_utilization_num
,source_sys_id
,facility_utilization
,case when source_sys_id in ('AFSEAST','AFSLSAL','DFBDOM','ACBS')
then right('000000000000000' + substring(source_sys_obligation_id,6,10),16)
when source_sys_id in ('MLSTLEND')
then right('000000000000000' + left(source_sys_obligation_id,15),16)
else '' end as No
from BridgeUnderwrite.dbo.t_sag_pimsc1
where source_sys_id in ('AFSEAST','AFSLSAL','DFBDOM','ACBS','MLSTLEND')
order by source_sys_id
;
The error is in reference to the set statements. They should look like:
if facility_utilization in ('F')
set #source_sys_obligation_id = source_sys_facility_id
else
set #source_sys_obligation_id = source_sys_utilization_num;
That ought to do it :) . . . however, source_sys_facility_id and source_sys_utilization_num are most likely going to be your next issues . . . are they variables (or perhaps parameters passed in) as well?
The '#' is part of the name. All T-SQL variable names or procedure parameters have to begin with this character (I assume the reason is so they are easy to discern from table and column names). So you probably need to say set #source_sys_obligation_id ... instead of set source_sys_obligation_id ....
What you want and what you can have are not the same! You cannot create a field in a select stament and then reference it in the same select statment in a case. Your code makes no sense at all and indcates a severe lack of understanding of how variables work.
declare #source_sys_obligation_id varchar(40);
if facility_utilization in ('F')
set source_sys_obligation_id = source_sys_facility_id
else set source_sys_obligation_id = source_sys_utilization_num;
This does not add columns to a select nor would it even populate anything even adding the #sign as some others have suggested because you do not have a select here. Further a variable can only have one value, not a different value per record. So scrap this whole approach. What you really need is a derived table or a CTE. You could also simply embed the first case in the second case. Something like this might get waht you are asking for:
SELECT a.source_sys_utilization_num
,a.source_sys_id
,a.facility_utilization
,CASE WHEN a.source_sys_id in ('AFSEAST','AFSLSAL','DFBDOM','ACBS')
THEN RIGHT('000000000000000' + SUBSTRING(a.source_sys_obligation_id,6,10),16)
WHEN a.source_sys_id in ('MLSTLEND')
THEN RIGHT('000000000000000' + LEFT(a.source_sys_obligation_id,15),16)
ELSE '' END AS [No]
FROM
(SELECT
source_sys_utilization_num
,source_sys_id
,facility_utilization
,CASE WHEN facility_utilization = 'F' THEN source_sys_facility_id
ELSE source_sys_utilization_num END AS source_sys_obligation_id
FROM BridgeUnderwrite.dbo.t_sag_pimsc1
WHERE source_sys_id in ('AFSEAST','AFSLSAL','DFBDOM','ACBS','MLSTLEND')) a
ORDER BY source_sys_id
Too busy to write the other versions. Maybe someone else will supply.

DESCENDING/ASCENDING Parameter to a stored procedure

I have the following SP
CREATE PROCEDURE GetAllHouses
set #webRegionID = 2
set #sortBy = 'case_no'
set #sortDirection = 'ASC'
AS
BEGIN
Select
tbl_houses.*
from tbl_houses
where
postal in (select zipcode from crm_zipcodes where web_region_id = #webRegionID)
ORDER BY
CASE UPPER(#sortBy)
when 'CASE_NO' then case_no
when 'AREA' then area
when 'FURNISHED' then furnished
when 'TYPE' then [type]
when 'SQUAREFEETS' then squarefeets
when 'BEDROOMS' then bedrooms
when 'LIVINGROOMS' then livingrooms
when 'BATHROOMS' then bathrooms
when 'LEASE_FROM' then lease_from
when 'RENT' then rent
else case_no
END
END
GO
Now everything in that SP works but I want to be able to choose whether I want to sort ASCENDING or DESCENDING.
I really can't fint no solution for that using SQL and can't find anything in google.
As you can see I have the parameter sortDirection and I have tried using it in multiple ways but always with errors... Tried Case Statements, IF statements and so on but it is complicated by the fact that I want to insert a keyword.
Help will be very much appriciated, I have tried must of the things that comes into mind but haven't been able to get it right.
You could use two order by fields:
CASE #sortDir WHEN 'ASC' THEN
CASE UPPER(#sortBy)
...
END
END ASC,
CASE #sortDir WHEN 'DESC' THEN
CASE UPPER(#sortBy)
...
END
END DESC
A CASE will evaluate as NULL if none of the WHEN clauses match, so that causes one of the two fields to evaluate to NULL for every row (not affecting the sort order) and the other has the appropriate direction.
One drawback, though, is that you'd need to duplicate your #sortBy CASE statement. You could achieve the same thing using dynamic SQL with sp_executesql and writing a 'ASC' or 'DESC' literal depending on the parameter.
That code is going to get very unmanageable very quickly as you'll need to double nest your CASE WHEN's... one set for the Column to order by, and nested set for whethers it's ASC or DESC
Might be better to consider using Dynamic SQL here...
DECLARE #sql nvarchar(max)
SET #sql = '
Select
tbl_houses.*
from tbl_houses
where
postal in (select zipcode from crm_zipcodes where web_region_id = ' + #webRegionID + ') ORDER BY '
SET #sql = #sql + ' ' + #sortBy + ' ' + #sortDirection
EXEC (#sql)
You could do it with some dynamic SQL and calling it with an EXEC. Beware SQL injection though if the user has any control over the parameters.
CREATE PROCEDURE GetAllHouses
set #webRegionID = 2
set #sortBy = 'case_no'
set #sortDirection = 'ASC'
AS
BEGIN
DECLARE #dynamicSQL NVARCHAR(MAX)
SET #dynamicSQL =
'
SELECT
tbl_houses.*
FROM
tbl_houses
WHERE
postal
IN
(
SELECT
zipcode
FROM
crm_zipcodes
WHERE
web_region_id = ' + CONVERT(nvarchar(10), #webRegionID) + '
)
ORDER BY
' + #sortBy + ' ' + #sortDirection
EXEC(#dynamicSQL)
END
GO