T-SQL and decision making constructs - sql

Please help me with the syntax of this query. It doesn't compile. It says there's a syntax error near the keyword END.
Obviously, I've got these BEGINs and ENDS mixed up.
I am using Microsoft SQL Server 2008 R2. I am not sure of the syntax of these BEGINS and ENDs.
Please don't mind the condition 1 = 0. That's something that will be replaced with a proper predicate later.
IF EXISTS (SELECT * FROM StringCategory WHERE ResourceKeyId = 18134 AND CategoryId = 0)
BEGIN
UPDATE StringCategory
SET CategoryId = 0
WHERE ResourceKeyId = 18134
END
ELSE
BEGIN
IF 1 = 0
BEGIN
DELETE FROM StringCategory WHERE ResourceKeyId = 18134
END
ELSE
BEGIN
INSERT INTO StringCategory
VALUES(18134, 0)
END
END
END

Your last END is an extra. You can think of the BEGINs and ENDs like { and } in C# for the IF constructs (They serve to mark the beginning and end of the block to be executed in the IF/ELSE statement).

Here is a much simpler way to do what you appear to be attempting.
insert into StringCategory
(ResourceKey, CategoryId)
select 18134, 0
where not exists (
SELECT *
FROM StringCategory
WHERE ResourceKeyId = 18134
AND CategoryId = 0)

Related

GETTING ERROR-- ORA-00936:MISSING EXPRESSION for below query please help on this

SELECT CASE (SELECT Count(1)
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(
SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988')
)
WHEN 0 THEN
(
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27' )
WHEN 1 THEN
(
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
ELSE NULL
END
FROM dual;
You need to recreate your query and make sure to follow the flow of the clauses properly, please check the next two links to get a better understanding :
[ORA-00936: missing expression tips]
How do I address this ORA-00936 error?
Answer: The Oracle oerr utility notes this about the ORA-00936 error:
ORA-00936 missing expression
Cause: A required part of a clause or expression has been omitted. For example, a SELECT statement may have been entered without a list of columns or expressions or with an incomplete expression. This message is also issued in cases where a reserved word is misused, as in SELECT TABLE.
Action: Check the statement syntax and specify the missing component.
The ORA-00936 happens most frequently:
1 - When you forget list of the column names in your SELECT statement.
2. When you omit the FROM clause of the SQL statement.
ora-00936-missing-expression
I hope this can help you.
You cannot use a simple select query like this. You have to use a PL/SQL block like below -
DECLARE NUM_CNT NUMBER := 0;
BEGIN
SELECT Count(1)
INTO NUM_CNT
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988');
IF NUM_CNT = 0 THEN
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27';
ELSIF NUM_CNT = 1 THEN
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
END IF;
END;

How to use case when in SQL Server 2008

I want to use case after where clause in SQL Server 2008; how can I use it like
select *
from MPR
where
case when #min >= 0
then MainComponent_Id = #mainc and SubComponent_Id = #subcomp
else MainComponent_Id = #mainc and SubComponent_Id = #subcomp and MinorComponent_Id = #minorc
end
end
I am using a stored procedure, and in my stored procedure if minorcomponent_id value is 0 then it will add 1 one else 2 one will work.
I had tried hard but its giving error in near case.
How to resolve it?
Thanks
You don't need to use a CASE statement. You can simplify logic as follows:
select
*
from
MPR
where
MainComponent_Id = #mainc AND SubComponent_Id = #subcomp
AND (#min >= 0 OR MinorComponent_Id = #minorc)

MSSQL 2008: Problems with the 'Case' - statement

I'm having some troubles finding a solution to my SQL-Problem. I've tried google but so far my search didn't give me any statisfactory results.
I have an SSRS report with two parameters:
#SupplierId NVARCHAR (May contain NULL)
#EmployeeId NVARCHAR (May contain NULL)
My original query retrieved all the employees who came in service during the last year:
SELECT Name, Surname from dbo.Employee Where Employee.DateInService > DATEADD(year,-1,GETDATE())
Right now i want to add those parameters to the query using the following logic.
Remark this is pseudo SQL:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
IF (LEN(RTRIM(#SupplierId)) = 0 Or #SupplierID IS NULL ) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
My search sofar led me to the Case statement. I made a query which contains an syntax error (obviously). My base query:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
Error: Syntax error near '='.
Question 1: Why does he give an error near the '='?
Question 2: How do i correctly implement the following:
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0 "Or #SupplierId is null" ) THEN
Instead of
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) Then dbo.Employee.EmployeeId = #EmployeeId
WHEN (#SupplierId IS NULL) Then dbo.Employee.EmployeeId = #EmployeeId
ELSE dbo.Employee.EmployeeId = #EmployeeId END
Note: if i've missed a post during my google searches, please don't hesitate to point it out.
Thanks for your help
You can't change the actual query predicate like that with CASE - there are 2 distinct queries depending on the value of #SupplierId. You can conditionally apply the filter as follows (I've assumed the #SupplierId = null flow is the same as the whitespace branch:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE())
AND
(
(dbo.Employee.EmployeeId = #EmployeeId
AND (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL))
OR
(dbo.Employee.SupplierId = #SupplierId AND LEN(RTRIM(#SupplierId)) > 0)
)
Although this can be prone to query plan sniffing related performance issues, in which case you might need to consider an alternative approach, e.g. using parameterized dynamic sql to build up and execute the sql, as there are 2 distinct process flows through the query.
Edit
As per Ypercube's comment above, in order to provide the boolean result needed for the predicate, if you can find a hack workaround is to find a way to project a COMMON scalar from each of the CASE .. WHEN row and then do a comparison of the scalar. In the example below, projecting a yes / no flag.
SELECT * FROM dbo.Employee
WHERE
CASE
WHEN (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL)
THEN CASE WHEN dbo.Employee.EmployeeId = #EmployeeId THEN 1 ELSE 0 END
ELSE CASE WHEN dbo.Employee.SupplierId = #SupplierId THEN 1 ELSE 0 END
END = 1;
But the big problem with this approach is performance - the above will require a full scan to determine the results.

Procedure stops when legacy, new error traps are next to each other

We have a bunch of old stored procedures with legacy style error trapping. I changed one the other day and included a newer TRY...CATCH block. The stored procedure just stopped after the TRY/CATCH and returned as though there were an error in the legacy block.
If I put a
SELECT NULL
in between the two everything works fine. Anyone know why this is happening?
--BEGIN NEW ERROR TRAP--
BEGIN TRY
Do stuff...
END TRY
BEGIN CATCH
END CATCH
--END NEW ERROR TRAP---
----------------- OLD SCHOOL TRAP BEGIN -----------------
SELECT #spERROR = ##ERROR ,
#spROWCOUNT = ##ROWCOUNT
SET #spRETURN = #spRETURN + 1
IF ( #spROWCOUNT <= 0
OR #spERROR <> 0
)
SET #spRETURN = 0 - #spRETURN
IF ( #spROWCOUNT <= 0
OR #spERROR <> 0
)
RETURN #spRETURN
SELECT #spROWCOUNT = -1 ,
#spERROR = -1
------------------ OLD SCHOOL ERROR TRAP END ------------------
In your try catch block, the last statement is probably doing something that sets the row count to 0. The "SELECT NULL" is setting the row count to 1, since it returns one row, so no error is detected.
You can fix this by changing the logic in the "old" code or by setting your row count variable in the try/catch code. I would recommend that you remove the SELECT NULL, since it would guarantee success and you may not want that behavior.

Stored procedure to find next and previous row in SQL Server 2005

Right now I have this code to find next and previous rows using SQL Server 2005. intID is the gallery id number using bigint data type:
SQL = "SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec FROM gallery AS p CROSS JOIN gallery AS n where p.galleryid < '"&intID&"' and n.galleryid > '"&intID&"'"
Set rsRec = Server.CreateObject("ADODB.Recordset")
rsRec.Open sql, Conn
strNext = rsRec("nextrec")
strPrevious = rsRec("previousrec")
rsRec.close
set rsRec = nothing
Problem Number 1:
The newest row will return nulls on the 'next record' because there is none. The oldest row will return nulls because there isn't a 'previous record'. So if either the 'next record' or 'previous record' doesn't exist then it returns nulls for both.
Problem Number 2:
I want to create a stored procedure to call from the DB so intid can just be passed to it
TIA
This will yield NULL for previous on the first row, and NULL for next on the last row. Though your ordering seems backwards to me; why is "next" lower than "previous"?
CREATE PROCEDURE dbo.GetGalleryBookends
#GalleryID INT
AS
BEGIN
SET NOCOUNT ON;
;WITH n AS
(
SELECT galleryID, rn = ROW_NUMBER()
OVER (ORDER BY galleryID)
FROM dbo.gallery
)
SELECT
previousrec = MAX(nA.galleryID),
nextrec = MIN(nB.galleryID)
FROM n
LEFT OUTER JOIN n AS nA
ON nA.rn = n.rn - 1
LEFT OUTER JOIN n AS nB
ON nB.rn = n.rn + 1
WHERE n.galleryID = #galleryID;
END
GO
Also, it doesn't make sense to want an empty string instead of NULL. Your ASP code can deal with NULL values just fine, otherwise you'd have to convert the resulting integers to strings every time. If you really want this you can say:
previousrec = COALESCE(CONVERT(VARCHAR(12), MIN(nA.galleryID)), ''),
nextrec = COALESCE(CONVERT(VARCHAR(12), MAX(nB.galleryID)), '')
But this will no longer work well when you move from ASP to ASP.NET because types are much more explicit. Much better to just have the application code be able to deal with, instead of being afraid of, NULL values.
This seems like a lot of work to get the previous and next ID, without retrieving any information about the current ID. Are you implementing paging? If so I highly recommend reviewing this article and this follow-up conversation.
Try this (nb not tested)
SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec
FROM gallery AS p
CROSS JOIN gallery AS n
where (p.galleryid < #intID or p.galleryid is null)
and (n.galleryid > #intID or n.galleryid is null)
I'm assuming you validate that intID is an integer before using this code.
As for a stored procedure -- are you asking how to write a stored procedure? If so there are many tutorials which are quite good on the web.
Since Hogan contributed with the SQL statement, let me contribute with the stored proc part:
CREATE PROCEDURE spGetNextAndPreviousRecords
-- Add the parameters for the stored procedure here
#intID int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec
FROM gallery AS p
CROSS JOIN gallery AS n
where (p.galleryid < #intID or p.galleryid is null)
and (n.galleryid > #intID or n.galleryid is null)
END
And you call this from code as follows (assuming VB.NET):
Using c As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString)
c.Open()
Dim command = New SqlCommand("spGetNextAndPreviousRecords")
command.Parameters.AddWithValue("#intID", yourID)
Dim reader as SqlDataReader = command.ExecuteReader()
While(reader.Read())
' read the result here
End While
End Using