Hide SELECT results in Procedure - sql

Within a stored procedure, I have a logic check that will throw an error & break my procedure if a SELECT statement returns any results, like so:
-- set breakpoint if true:
SELECT myid, COUNT(*) AS [Records]
FROM #mytemptable
GROUP BY myid
HAVING COUNT(*) > 1
IF ##ROWCOUNT > 0
BEGIN;
THROW 51000,'ERROR - this is wrong', 1
END
This correctly breaks my report when [Records] > 1. When there are no results however, I need to suppress the output of this empty SELECT query (reason being, this procedure feeds several downstream procedures).
This procedure also returns several other SELECT results that I do not want to suppress. How can I hide only this one empty result?

How about using IF and EXISTS?
IF EXISTS (SELECT myid, COUNT(*) AS [Records]
FROM #mytemptable
GROUP BY myid
HAVING COUNT(*) > 1
)
BEGIN
THROW 51000,'ERROR - this is wrong', 1
END;
BEGIN doesn't traditionally take a semicolon after it.

Related

Conditionally insert and return rowid or 0?

I know how to do this using a transaction but I was wondering if I can do this in a single line. My actual query is more complex but the part I can't figure out is how to get the rowid or 0 without repeating the where clause
insert into comment
(select #text, #userid, #date)
where (select count(*) from comment where body=#text and userid=#userid) == 0
select last_insert_rowid()
If your version of SQLite is 3.35.0+ you can use the RETURNING clause to get the rowid of the inserted row like this:
WITH cte(body, userid, date) AS (SELECT #text, #userid, #date)
INSERT INTO comment (body, userid, date)
SELECT c.*
FROM cte c
WHERE NOT EXISTS (SELECT * FROM comment t WHERE (t.body, t.userid) = (c.body, c.userid))
RETURNING rowid;
The drawback is that in case of a failed insertion the query returns nothing.
If your app can check the number of returned rows you can translate that as 0.
See the demo.
Do nothing. Your query already returns 0 if there was no update.
The last_insert_rowid documentation says
The last_insert_rowid() SQL function is a wrapper around the sqlite3_last_insert_rowid() C/C++ interface function.
And the documentation for sqlite3_last_insert_rowid says
If no successful INSERTs ... have ever occurred ..., then sqlite3_last_insert_rowid(D) returns zero.

In a stored procedure how to skip to next query statement even if the previous statement fails

I'm hoping someone can give me an idea on how to handle this situation. I have a stored procedure that updates various tables. Some queries require connecting to different linked servers. Sometimes those linked servers are down and i need the procedure to still run the next statements regardless. Below is an example:
--Stored Procedure
BEGIN
INSERT INTO table1
SELECT *
FROM Z1;
-- IF ABOVE FAILS GO TO NEXT QUERY ANYWAY
INSERT INTO table1
SELECT *
FROM Z2;
-- IF ABOVE FAILS GO TO NEXT QUERY ANYWAY
INSERT INTO table1
SELECT *
FROM Z3;
END
You can probably do what you want with TRY/CATCH blocks:
BEGIN
BEGIN TRY
INSERT INTO table1 SELECT * FROM Z1;
END TRY
BEGIN CATCH
-- you can do something here if you want
END CATCH;
-- IF ABOVE FAILS GO TO NEXT QUERY ANYWAY
BEGIN TRY
INSERT INTO table1 SELECT * FROM Z2;
END TRY
BEGIN CATCH
-- you can do something here if you want
END CATCH;
-- IF ABOVE FAILS GO TO NEXT QUERY ANYWAY
BEGIN TRY
INSERT INTO table1 SELECT * FROM Z3;
END TRY
BEGIN CATCH
-- you can do something here if you want
END CATCH;
END;
This handles runtime errors. If you have compile time errors -- such as tables not existing or the columns not matching between the tables, then this doesn't help.
If this were run from say ssms as a bunch of ordinary queries, I would've put batch separators between each of them to treat them separately. However since this is a stored procedure you can't do that. One way to get around that could be to make one stored procedure of each query and put all of them as steps inside a SQL Server Agent job. You run the job and each step runs in order from top to bottom even if some in the middle fail.
even this will also work: ##ROWCOUNT is oracle's equivalent of sql%rowcount
--Stored Procedure
BEGIN
INSERT INTO table1
SELECT *
FROM Z1;
IF ##ROWCOUNT <>1
INSERT INTO table1
SELECT *
FROM Z2;
IF ##ROWCOUNT <>1
INSERT INTO table1
SELECT *
FROM Z3;
END

How to get row count of select statement inside stored procedure in SQL Server

I have requirement where I want get row count of select statement inside stored procedure and if row count is equal to 0 then only it will execute the next statement
select A, B, C
from AT
where B = 1
If the above statement returns any rows, then it will not execute further but if this statement do not have any row then it will execute next statement. I have tried it using in two ways
##rowcount - it's not working properly
Using temp table by inserting select statement into table getting row count of table but using temp table is not optimize way
Is there any solution?
You could use IF NOT EXISTS:
IF NOT EXISTS (select A,B,C from AT where B=1)
BEGIN
-- sth
END
is there any solution like getting into variable without hitting to database again and again
DECLARE #my_rowcount INT;
select A,B,C from AT where B=1;
SET #my_rowcount = ##ROWCOUNT; -- immediately after select get ##ROWCOUNT
...
IF #my_rowcount = 0
BEGIN
-- sth
END
EDIT:
##ROWCOUNT Globle variable for database so it may return wrong Value if any other select statement processed in other sp in same databe
Nope. ##ROWCOUNT:
Returns the number of rows affected by the last statement.
You could easily check it with your SSMS(open 2 tabs, select 1 and 2 rows on each of them and then get ##ROWCOUNT respectively).

"Order by" works in Console but doesn't work in Stored Procedures

I've a problem executing a Stored Procedure in Informix. I'm doing a simple query that it doesn't work. This is the query:
SELECT
first 1 field1,
date1
FROM
historia_t
WHERE
field3 = 1
AND field4 = 1
AND date1 BETWEEN (CURRENT - 1 UNITS YEAR) AND CURRENT
ORDER BY
field1 desc
If I execute the query in DbVisualizer I don't have any problem but if I execute the query in Informix(With stored procedures) I get a sintaxis error in the line with " AND date1 BETWEEN (CURRENT - 1 UNITS YEAR) AND CURRENT " . But the real problem it's in ORDER BY field1 desc;
I don't know why, but sometimes Stored Procedures return errors when you use Order by in them.
Note: Fields are invented because I think they aren't important for the problem.
Thanks in advanced!
When you run a SELECT statement via DB-Access or equivalent, the program takes care of creating a cursor, opening it, fetching the data, closing the cursor, and freeing up the resources used.
Inside a stored procedure, you have to manage this processing. The FOREACH loop does that automatically. If you're using dynamic SQL, there are other statements you can use.
If a SELECT statement may return more than one row, you need the cursor management. If the SELECT statement returns just a single row, you can specify which variable should receive the result. I observe that ORDER BY is immaterial when the SELECT returns a single row — if you have an ORDER BY, there'll be a strong presumption that the query might return more than one row.
For example, this stored procedure works (and returns syssynonyms):
create procedure fk2() returning varchar(128) as tabname;
define t varchar(128);
select tabname into t from informix.systables where tabid = 9;
return t;
end procedure;
But where there's more than one row, you need:
create procedure fk3() returning varchar(128) as tabname;
define t varchar(128);
foreach select tabname into t
from informix.systables
where tabid between 4 and 10
order by tabname # No semicolon permitted (don't ask!)
return t with resume;
end foreach;
end procedure;
This returns:
syscolauth
sysdepend
syssynonyms
syssyntable
systabauth
sysusers
sysviews

How to return a failure if a table is empty

Using SQL Server 2005, but still using DTS. I need to add a step to check if a table is empty, and somehow fail the step if it is. It's easy checking if the table is empty:
Select count(*) from source_table
But returning 0 is a success, too. If it is 0, I want a failure (so that I can fork to a different option, email us, skip some steps).
if (select count(*) from [Table]) = 0 print 'Empty'
what about returning -1 ?
Select
case when count(*)>=0 then count(*) else -1 end
from
source_table
If you really want to raise an error, you can use RAISERROR to do just that :
Declare #RowCount as bigint
set #RowCount=count(*) from source_table
if RowCount =0
RAISERROR ('error message', 50000, 1) with log
You can divide by count result:
Select 1/count(*) from source_table
I didn't use DTS. It was resolved in SSIS, although, looking back, I could have probably done something similar in DTS.
Step 1: A data flow task that selects count and saves that count to a variable. The select count took a bit of work:
select cast(count(*) as integer) as Row_Count from MyTable
and then the output of the data flow task was a script component that was a destination and had an input column as that ROW_COUNT, and my ReadWriteVariables as TableCount (the variable that was used as input in step 2)
Step 2: A script task that evaluates that count and fails if the count was 0, succeeds otherwise. Forking from this is a success route and a failure route.