Performance Issue due to GOTO statement - sql-server

I'm using SQL Server 2016 database project and my script is like below
DECLARE Marker NVARCHAR(50) = (SELECT Value FROM Table1 WHERE name = 'Marker')
IF( IS NOT NULL)
BEGIN
IF #Marker = 'Marker1' GOTO Marker2;
IF #Marker = 'Marker2' GOTO Marker3;
IF #Marker = 'Marker3' GOTO Marker4;
IF #Marker = 'Marker4' GOTO Marker5;
IF #Marker = 'Marker5' GOTO Marker6;
IF #Marker = 'Marker6' GOTO Marker7;
ELSE GOTO EmptyBlock;
END
MARKER1:
Code for marker 1
MARKER2:
Code for marker 2
MARKER3:
Code for marker 3
.
.
.
EmptyBlock:
PRINT 'No changes'
This script file will be executed after every deployment and based on deployment it will be skipping the previous lines and now it will be reached to marker 15.
It's taking too much time to execute even though there are few lines of code, I've finally found the issue due to GOTO statements. I don't know if using GOTO is best practice or not, if its not good practice using it in production site then please give me the suggestions for an alternate of GOTO.

You can replace the GOTO statements with a script like this using IF:
-- get the number of the marker (instead of the full name of the marker).
DECLARE #Marker INT = (SELECT REPLACE(Value, 'Marker', '') FROM Table1 WHERE name = 'Marker')
IF #Marker IS NULL
BEGIN
PRINT 'no marker'
END
IF #Marker < 1
BEGIN
-- Code for Marker No. 1
END
IF #Marker < 2
BEGIN
-- Code for Marker No. 2
END
IF #Marker < 3
BEGIN
-- Code for Marker No. 3
END
IF #Marker < 4
BEGIN
-- Code for Marker No. 4
END
ELSE IF #Marker IS NOT NULL
BEGIN
PRINT 'no changes'
END
demo on dbfiddle.uk

Related

Working with nested loops in pl/sql but not displaying the proper output

SET SERVEROUTPUT ON SIZE 4000;
DECLARE
call_id COURSE.CALL_ID%type;
sec_num COURSE_SECTION.SEC_NUM%type;
fname STUDENT.S_FIRST%TYPE ;
lname STUDENT.S_LAST%TYPE;
CURSOR c_info is
SELECT CALL_ID , SEC_NUM
FROM COURSE_SECTION ,COURSE,TERM
WHERE COURSE_SECTION.COURSE_ID = COURSE.COURSE_ID
AND TERM.TERM_ID = COURSE_SECTION.TERM_ID
AND TERM.TERM_DESC = 'Summer 2007' ;
CURSOR S_NAME IS
SELECT DISTINCT S_FIRST, S_LAST
FROM STUDENT,COURSE_SECTION,TERM,ENROLLMENT
WHERE TERM.TERM_ID = COURSE_SECTION.TERM_ID
AND COURSE_SECTION.C_SEC_ID = ENROLLMENT.C_SEC_ID
AND COURSE_SECTION.TERM_ID=TERM.TERM_ID
AND ENROLLMENT.S_ID = STUDENT.S_ID
AND TERM.TERM_DESC LIKE 'Summer 2007';
BEGIN
OPEN c_info;
LOOP
FETCH c_info INTO call_id , sec_num ;
EXIT WHEN c_info%notfound;
DBMS_OUTPUT.PUT_LINE('==================================');
DBMS_OUTPUT.PUT_LINE(call_id || ' ' || 'Sec. ' || sec_num);
DBMS_OUTPUT.PUT_LINE('==================================');
OPEN S_NAME;
LOOP
FETCH S_NAME INTO fname , lname ;
EXIT WHEN S_NAME%notfound;
DBMS_OUTPUT.PUT_LINE(fname || ' ' || lname );
END LOOP;
CLOSE S_NAME ;
END LOOP;
CLOSE c_info;
END;
-- The output expected
-- I have having some issues, I am unable to display the proper output. I am trying to use a nested loop but i made some mistake when implementing it. Plus i think an explicit cursor is much better to be used.
Make use of the Northwood university database.
https://drive.google.com/file/d/1M_g7FbgOUahoFtE943OK28UxIFbUFgRk/view?usp=sharing
The script
I'm making a lot of assumptions here - I'm guessing you are getting all students for all courses in your inner loop, but you really just want get students for the particular course section you are dealing with in your outer loop.
So your second query will need to reference the right course section ID to limit the students to just that section.
You don't need to explicitly define cursors unless you need them for some reason - if you just iterating through them, its better to reference them directly in the FOR loop.
So that brings me to the following
set serveroutput on size 4000;
begin
for c_info in (
select call_id,
sec_num,
SEC_ID -- PK to link to enrollment later
from course_section,
course,
term
where course_section.course_id = course.course_id
and term.term_id = course_section.term_id
and term.term_desc = 'Summer 2007' ;
)
loop
dbms_output.put_line('==================================');
dbms_output.put_line(c_info.call_id || ' ' || 'Sec. ' || c_info.sec_num);
dbms_output.put_line('==================================');
for s_name in (
select distinct s_first, s_last
from student,
course_section,
term,
enrollment
where term.term_id = course_section.term_id
and course_section.c_sec_id = enrollment.c_sec_id
and course_section.term_id=term.term_id
and enrollment.s_id = student.s_id
and term.term_desc like 'Summer 2007'
AND ENROLLMENT.C_SEC_ID = C_INFO.SEC_ID -- get students just for THIS course section
)
loop
dbms_output.put_line(s_name.s_first || ' ' || s_name.s_last );
end loop;
end loop;
end;
where I've put query alterations in CAPS.
Since I cut/pasted your SQL there are no aliases in the first query - I'd recommend you correct that, as aliasing columns is always good practice.
Simiarly, I retained the DISTINCT in the second query, but I'd suspect its redundant, because I imagine a student wont enroll more than once for a single course section. (And in reality, if you had two different students named Sue Smith, you would probably want to print them out twice, no?)

Netezza while loop syntax

I want to make a statement in netezza so that it waits until a statement is correct before proceeding. Any help would be appreciated - something similar to the below
WHILE (
select count(*) EVENT_DESCRIPTION from TEST_DA_CONTROL.CTRL.C_DBA_MAINTENANCE_AUDIT
where EVENT_DESCRIPTION = 'STARTED' and DATETIME_LOGGED > (select add_months(current_date,0))) = 0
LOOP
wait 5
end loop;
but I don't know the correct syntax.
Best to assign that output to a variable. I seem to recall that getting data out of an execute immediate is a little arduous in nzplsql, but there are convenient variables already available for you to use. Here I'll use ROW_COUNT.
declare
event_descriptions int;
sql varchar;
begin
event_descriptions := 1;
while event_descriptions > 0 loop
--Actual work
sql := '
select * EVENT_DESCRIPTION from TEST_DA_CONTROL.CTRL.C_DBA_MAINTENANCE_AUDIT
where EVENT_DESCRIPTION = ''STARTED'' and DATETIME_LOGGED > (select add_months(current_date,0))) = 0;';
execute immediate sql;
event_descriptions := ROW_COUNT;
end loop;
end;

How do i format a sql numeric type with commas on Sybase SQLAnywhere?

I came across the following solution but it does not work on Sybase
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
I have read the Convert Sybase information but still i receive the same number without the commas.
Have you tried giving a varchar (20) for example instead ? something like :
SELECT CONVERT(varchar(20), CAST(987654321 AS money), 1)
In SqlAnywhere money datatype is a domain, implemented as NUMERIC(19,4).
in CAST function , If you do not indicate a length for character string types, the database server chooses an appropriate length. If neither precision nor scale is specified for a DECIMAL conversion, the database server selects appropriate values.
So maybe this is what's causing the issue, what do you get as output ? do you get 987654321.00 , or just 987654321 ?
Update:
My last suggestion would be using insertstr() function and loop through the char value of your number to insert comma every 3 digits .. this is not the cleanest/easiest way but apparently SQLAnywhere deal with money datatype as normal NUMERIC datatype ...
insertstr() documentation is here.
I would give you a code sample but I don't have SQLAnywhere installed to test it ...
Here is the SP i created based on F Karam suggestion.
CREATE FUNCTION "DBA"."formattednumber"( in #number numeric)
returns char(60)
begin
declare #returnnumber char(60);
declare #workingnumber char(60);
declare #n_ind char(1);
declare #decimalnumber char(10);
declare #tempnumber char(60);
declare #decimalpos integer;
if isnull(#number,'') = '' then
return null
end if;
if #number < 0 then set #n_ind = 'Y'
else set #n_ind = 'N'
end if;
set #workingnumber = convert(char(60),ABS(#number));
set #decimalpos = patindex('%.%',#workingnumber);
if #decimalpos > 0 then
set #decimalnumber = substr(#workingnumber,#decimalpos);
set #decimalnumber = "left"(#decimalnumber,3+1);
set #workingnumber = "left"(#workingnumber,#decimalpos-1)
end if end if;
set #returnnumber = '';
while length(#workingnumber) > 3 loop
set #tempnumber = "right"(#workingnumber,3);
set #returnnumber = insertstr(0,#returnnumber,#tempnumber);
set #workingnumber = "left"(#workingnumber,length(#workingnumber)-3);
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,',')
end if
end loop;
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,#workingnumber)
end if;
if length(#decimalnumber) > 0 then
set #returnnumber = #returnnumber+#decimalnumber
end if;
if #n_ind = 'Y' then set #returnnumber = '-' || #returnnumber
end if;
return(#returnnumber)
end;
You need to distinguish between server-side and client-side formatting. When you use the 'isql' client for example (the TDS client), then the result will be this:
1> select convert(money, 9876543210)
2> go
9876543210
------------------------
9,876,543,210.00
(1 row affected)
But this is purely because the client application happens to format 'money' values this way. Also, this is actually not specific for SQLA, since isql is originally the client tool for ASE (a different Sybase database).
When you run the same conversion at the SQLA server (i.e. as part of an expression in a SQL statement), those commas will not be there since SQLA doesn't have such a built-in formatting style.
If you want this, you should write a SQL function that formats the number as you desire.

IF ELSE syntax error

My IF..ELSE block fails at BEGIN. I can understand how my expression is not boolean in nature, but what is causing this failure?
IF (SUBSTRING(#PARIDIN,1,1) = 'P'
BEGIN
SET #PARIDTEMP = SUBSTRING(LTRIM(RTRIM(#PARIDIN)),2,6))
END
BEGIN
ELSE SET #PARIDTEMP = #PARIDIN
END
You have an extra set of parentheses in a weird place.:
IF SUBSTRING(#PARIDIN,1,1) = 'P' -- one at the beginning of this line.
BEGIN
SET #PARIDTEMP = SUBSTRING(LTRIM(RTRIM(#PARIDIN)),2,6) -- one at the end of this line.
END
ELSE
BEGIN
SET #PARIDTEMP = #PARIDIN
END
You are not closing the expression being evaluated.
Change
IF (SUBSTRING(#PARIDIN,1,1) = 'P'
To
IF (SUBSTRING(#PARIDIN,1,1) = 'P')
Taking everybody else's suggestion of fixing the condition I am surprised nobody mentioned the very strange BEGIN END blocks. They don't make sense and not sure they would even work. Since you have only a single statement for each it makes more sense to remove them.
IF (SUBSTRING(#PARIDIN,1,1) = 'P')
SET #PARIDTEMP = SUBSTRING(LTRIM(RTRIM(#PARIDIN)),2,6))
ELSE
SET #PARIDTEMP = #PARIDIN

Nested if in SQL Server

this is my query :
if (a)
begin
---
---
---
if (b)
---
else
---
end
when I remove 3 lines of this query ( line 6 and 7 and 8 ), it works ,, what's wrong with that query when I have all the lines
I should say the line 7 is just this : "return -23" and the line 9 is just this : delete tablename where ..
I mean as I know the second If doesn't need begin and end (?)
my main query is this :
if #Updatekind = 2
BEGIN
Delete SALFactorAddOns
Where SerialNoFhsFAO = #SerialNoFHS
and (CompanyNo = #CompanyNoFHS)
if ((select invsnfhs from SALFactorHds where (SerialNoFHS = #SerialNoFHS)
and (CompanyNo = #CompanyNoFHS) ) > 0 )
return -23
else
DELETE SALFactorHds
WHERE (SerialNoFHS = #SerialNoFHS)
and (CompanyNo = #CompanyNoFHS)
end
An If statement go with keywords BEGIN and END (statement block), if there is no statement block used, the IF or ELSE condition can affect the performance of only one Transact-SQL statement.
IF #a is null
Begin
-- code here
End
Read more about the syntax here
have you tried using the construct:
if (a)
begin
...
end
else if (b)
begin
...
end
else
begin
...
end
?

Resources