Getting only the length of returned string as result of an SQL query using Derby DB - sql

I want to test whether a length of a string returned from an SQL query is equal to 3. I'm using DERBY DB.
I've tried something like:
ij> select * from tmpuser.friends where length(select distinct ss.schemaname from sys.sysschemas ss fetch next 1 row only)=3;
But this query is invalid. I want to show the result of
select * from tmpuser.friends
only if
length(select distinct ss.schemaname from sys.sysschemas ss fetch next 1 row only)=3;
is true.
ij> select distinct ss.schemaname from sys.sysschemas ss;
SCHEMANAME
--------------------------------------------------------------------------------------------------------------------------------
APP
NULLID
SQLJ
SYS
SYSCAT
SYSCS_DIAG
SYSCS_UTIL
SYSFUN
SYSIBM
SYSPROC
SYSSTAT
TMPUSER
12 rows selected
ij> select distinct ss.schemaname from sys.sysschemas ss fetch next 1 row only;
SCHEMANAME
--------------------------------------------------------------------------------------------------------------------------------
APP
I want to do a test: is 'APP' length equal to 3?
I expect query will return an empty result if test if false, otherwise run the select statement.

I hope CASE expression will help in this case, can you try the query below:
select distinct CASE WHEN length(ss.schemaname) = 3 THEN ss.schemaname ELSE '' END AS SCHEMANAME
from sys.sysschemas ss
fetch next 1 row only;

Related

How to write a query which selects from a table that is returned by another query

I have table which has basically 2 rows containing the name of failure and the main table i want to write a query such that
Select main
from xyz
will return the table name like abc.
Now I want to get the data from the abc table
Select *
from
(select main
from xyz)
which returns abc.
How can I write it ?
You must use dynamic sql.
Note, that you can't use "SELECT to nowhere" in a compound statement in Db2. That is, the following code is erroneous.
BEGIN
SELECT * FROM MYTAB;
END#
This is why you need to store the result of SELECT somewhere. You may use Global Temporary Tables for that presuming, that USER TEMPORARY TABLESPASE is available to use for your user.
--#SET TERMINATOR #
BEGIN
DECLARE V_STMT VARCHAR (500);
SELECT
'DECLARE GLOBAL TEMPORARY TABLE SESSION.RESULT'
|| ' AS (SELECT * FROM '
|| MAIN
|| ') WITH DATA WITH REPLACE '
|| 'ON COMMIT PRESERVE ROWS NOT LOOGED'
INTO V_STMT
FROM XYZ
-- place your WHERE clause here if needed
FETCH FIRST 1 ROW ONLY
;
EXECUTE IMMEDIATE V_STMT;
END
#
SELECT * FROM SESSION.RESULT
#
dbfiddle link.
Here is a solution on stack that shows how to get the table names from your database
DB2 Query to retrieve all table names for a given schema
Then you could take your failure table and join into it based off of the table name, that should match your errors to the table that match on the table name. I'm not a 100% sure of your question but I think this is what you are asking.
The inner system query has schema and name. Type is T for table. See IBM link below for column reference. You could run the query wide open in the inner query to look for the tables you want. I would recommend using schema to isolate your search.
https://www.ibm.com/docs/en/db2-for-zos/11?topic=tables-systables
SELECT
ft.*
, st.*
FROM [FailureTable] as ft
INNER JOIN
(
select * from sysibm.systables
where CREATOR = 'SCHEMA'
and name like '%CUR%'
and type = 'T'
) st
ON st.[name] = ft.[tablename]
You can try
DECLARE #tableName VARCHAR(50);
SELECT #tableName = main
FROM xyx
EXEC('SELECT * FROM ' + 'dbo.' + #tableName)
Dont forget to add validation if #tableName doesnt get populated

Update operation failed with SQLCODE=-803, how to troubleshoot?

I am trying to update table records based on some condition. When I update few number of recent records it works fine but when I run it for more number records or older records it throws errors
Query :
update table_Name set Col1 = 'C'
where date(TRN_SCH_DPT_DT) < current date - 200 DAYS
Works fine!
update table_Name set Col1 = 'C'
where date(TRN_SCH_DPT_DT) < current date - 100 DAYS
Throws error => DB2 SQL Error:
SQLCODE=-803, SQLSTATE=23505, SQLERRMC=2
Note: I am not updating primary key. Any number greater than 200 is working fine.
There is a SELECT statement in the description of SQL0803N, which can help you find an unique index (with IID=2) your statement tries to violate.
SELECT INDNAME, INDSCHEMA
FROM SYSCAT.INDEXES
WHERE IID = 2
AND TABSCHEMA = 'TABLE_SCHEMA' AND TABNAME = 'TABLE_NAME'

Hide SELECT results in Procedure

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.

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).

(T-SQL): How do I use result set A to calculate result set B?

I have 2 queries, A and B, which I currently use independently from each other. They both return an employee ID and some metric values. I now want to use the employee IDs returned from result set A in query B.
A's query is structured like this:
select employee_id from employee where employee_team = 1 and employee_role = 1
B's query is structured like this:
declare #tester int = 123450 --plug in employee ID
select employee_id
,employee_name
,sum(case
when notes.note_author!=employee_id and logs.log_date<#today
then 1 else 0 end) as metric
from notes
inner join note_to_log_bridge as br on notes.note_id=br.note_id
inner join logs on br.log_id=logs.log_id
inner join employee on employee_id=#Tester
If I want to get B's metrics for 5 employees, I have to run query B 5 times, changing the #Tester variable each time. I'd like to instead find some way of automating that, so that I get the metrics for query B for every employee_id in result set A.
I tried stored result set A as a CTE and using a while loop to run through query B:
declare #line=1
with cte (employee_id) as <query_a>
while (#line<=count(cte.employee_id))
begin <query b>...
I never finished this query because I discovered that while cannot follow the creation of a CTE.
I tried using a table variable:
declare #set_a (employee_id int)
insert into #set_a <query a>
but when I try to use #set_a in query B, I get a message saying that I need to declare the scalar variable #set_a.
I tried using a temp table and got a "could not be bound" error.
I am out of ideas. Am I approaching this problem in anything resembling the right direction? Is this even possible?
Thank you!
Yes, you can use cursor and it will work perfectly fine.
But, if you have significantly more than 5 rows you may consider using CROSS APPLY to make it all in one query. It may work faster than cursor.
select
employee.employee_id
,CA.*
from
employee
CROSS APPLY
(
<put your query B here
and replace all references to parameter #Tester
with employee.employee_id>
) AS CA
where employee.employee_team = 1 and employee.employee_role = 1
You can think of this operator like this: for each row in the main outer query A CROSS APPLY runs the inner query B with the possibility to reference values of the row from the outer query A (in this case employee.employee_id).
Use Cursor ?
If I want to get B's metrics for 5 employees, I have to run query B 5
times, changing the #Tester variable each time.
DECLARE #empid int;
DECLARE vend_cursor CURSOR
FOR select employee_id from employee where employee_team = 1 and employee_role = 1
OPEN vend_cursor
FETCH NEXT FROM vend_cursor into #empid;
WHILE ##FETCH_STATUS = 0
BEGIN
// your query with #mpid
FETCH NEXT FROM db_cursor INTO #name
END
CLOSE vend_cursor
DEALLOCATE vend_cursor