counting rows returned by regexp_like - oracle

I need to count the number of rows returned by REGEXP_LIKE() in oracle. how do I do that?
I have tried the following query in a function:
RETURN COUNT(REGEXP_LIKE(SIN, '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$'));

Use regexp_count(https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions135.htm) instead of REGEXP_LIKE

SELECT COUNT(*) INTO sin_count FROM your_tbl WHERE REGEXP_LIKE(
SIN, '^(-|\+){0,1}([0-9]+\.[0-9]|[0-9]\.[0-9]+|[0-9]+)$');

Related

Oracle APEX apex_string.split order by

Does apex_string.split always guarantee that the order of the rows returned is the order of the characters of the string ?
Can I rely on the rownum to always correspond to 1 for the first character of the split string ?
or do I need to add a order by rownum ?
What is the method to get the rows in the same order of the characters of the string ?
My requirement is to insert the rows returned by apex_string.split in the same order as the characters of the string.
I am currently executing the below, will this maintain the character order ?
select t.column_value value, rownum seq
from table(apex_string.split('test','')) t
bulk collect into ins_arr;
for i in ins_arr.first..ins_arr.last
loop
/* execute insert statement */
insert into table (seq, value )
values (ins_arr.seq,ins_arr.value);
end loop
The insert should result in
seq
value
1
t
2
e
3
s
4
t
Thank you in advance,
I don't think it's guaranteed, becuase if it was, it would be in the documentation. But I think you can accomplish what you want by changing your routine. (Note, I have not verified this.)
insert into table (seq, value)
select t.column_value value,
row_number() over (order by t.column_value)
from table(apex_string.split('test','')) t
I think you can do the same with rownum, but I'm never 100% sure what order the rownum and the order by happen in.

How I can return varchar in Oracle

I have this record [sip:+3xxxxxxxxx#xxxx.xx;user=phone; tel:+3xxxxxxxxx;], [tel:+3xxxxxxxxxx;cpc=ordinary].
I want to return varchar from tel: to the ;. I was try with function **SUBSTR()**, but, because the position is not fixed at all records does not return accurate records. Аlso the, REGEXP_LIKE() function returns my full records not just the part I need. Can you tell me what is the best way to solve this problem.
Using REGEXP_SUBSTR we can try:
SELECT REGEXP_SUBSTR(col, 'tel:[^;]+;')
FROM yourTable;
Demo
Data:
WITH yourTable AS (
SELECT '[sip:+3xxxxxxxxx#xxxx.xx;user=phone; tel:+3xxxxxxxxx;], [tel:+3xxxxxxxxxx;cpc=ordinary]' AS col FROM dual
)

How to Have Function Definition and Subquery in With Clause of Oracle Select Statement?

I know the right syntax for having a function definition in the WITH clause. I know the right syntax for having a subquery in the WITH clause. But I have been unable to find an example of having a subquery and a function definition in the WITH clause of a SELECT statement.
If I have:
with totals as ( select colum_name from some_table )
select sum(column_name) from totals;
How do I add a function definition in the WITH clause?
Since you can't find much/anything about this from Oracle, I don't think it is a good idea to use it. Anyway, this works in 18.1:
WITH
FUNCTION with_plus(p IN NUMBER) RETURN NUMBER IS
BEGIN
RETURN p + 1;
END;
FUNCTION with_min(p IN NUMBER) RETURN NUMBER IS
BEGIN
RETURN p - 1;
END;
qry1 AS (
SELECT with_plus(10) plus
FROM DUAL
),
qry2 AS (
SELECT plus, with_min(10) min
FROM qry1
)
SELECT *
FROM qry2
;
/
So don't forget the slash / at the end.
If you ever find out how to put this whole block in a subquery, please let me know
I don't think there's any such restriction. However, I suspect that your problem has to do with column aliasing. Here's what worked for me:
with totals as (select sum(column_name) c1 from some_table)
select c1 from totals;
Oracle might have complained because you were trying to do something like:
with totals as (select sum(column_name) from some_table)
select sum(column_name) from totals;
Unfortunately, this is a consequence of name resolution. The subquery's column will get named "sum(column_name)". Since sum is a function, there's no way to reference that column name without Oracle thinking you're referencing the function. You have to give it another name in order to reference it anywhere else.
Edit: It seems that you want to define a function as if you would a view subquery. I don't think anything like this is possible. View subqueries really only perform textual substitution.
PL/SQL functions require a whole different parser, name resolution, compilation process, etc. Having them work in queries alone is hard enough.
Sorry to say, but you'd have to define your packages/procedures/functions normally.

ExistsNode - What's wrong

I create a table in oracle like this:
CREATE TABLE XML_TEMP (
XML_DATA CLOB
);
INSERT INTO XML_TEMP(XML_DATA) VALUES('
<envCFe versao="0.07" xmlns="http://www.fazenda.sp.gov.br/sat">
<tpAmb>1</tpAmb>
<idLote>4095</idLote>
<cUF>35</cUF>
<LoteCFe>
</LoteCFe>
<nSeg></nSeg>
<dhEnvio>20171101101517</dhEnvio>
</envCFe>
');
When I select the existsNode return 0
SELECT ExistsNode(XMLTYPE(XML_DATA), '/envCFe') HAS, XML_DATA FROM XML_TEMP;
I don't understang what's wrong, someone could help.
The link http://sqlfiddle.com/#!4/c2b9e/5/0 has the SQLFiddle
Your root node has a namespace, so you need to specify that using the optional third argument:
SELECT ExistsNode(XMLTYPE(XML_DATA), '/envCFe',
'xmlns="http://www.fazenda.sp.gov.br/sat"') HAS, XML_DATA
FROM XML_TEMP;
HAS XML_DATA
---------- --------------------------------------------------------------------------------
1
<envCFe versao="0.07" xmlns="http://www.fazenda.sp.gov.br/sat">
<tpAmb>1</tpAmb>
<idLote>4095</idLote>
<cUF>35</cUF>
<LoteCFe>
</LoteCFe>
<nSeg></nSeg>
<dhEnvio>20171101101517</dhEnvio>
</envCFe>
SQL Fiddle
If you intend to use ExistsNode to filter your results, and since that function is deprecated, you could use the XMLExists operator for that scenario instead:
SELECT XML_DATA
FROM XML_TEMP
WHERE XMLExists(
'declare namespace ns="http://www.fazenda.sp.gov.br/sat"; (: :)
/ns:envCFe'
PASSING XMLTYPE(XML_DATA)
);
SQL Fiddle
You can't get the result of that as part of a query result though, as your current query is doing.
You need to add the namespace to existsNode function:
SELECT ExistsNode(XMLTYPE(XML_DATA), '/envCFe', 'xmlns="http://www.fazenda.sp.gov.br/sat"') HAS, XML_DATA FROM XML_TEMP;

Oracle: How to create a function returning values for a "SELECT * FROM tab WHERE name IN (function())"

I have a problem which I can't solve. Maybe you have an idea about how to solve it.
I do have a given parameter-table like this:
P_VALUE P_NAME
----------- ----------
X85 A_03
XH1 A_04
XH2 A_04
XH3 A_04
C84 A_05
As you can see there are parameters with multiple entries. At the moment this parameters are used in this way:
SELECT * FROM tablex
WHERE code IN (SELECT p_value
FROM parameter_table
WHERE p_name LIKE 'A_04');
As the query is very big these parameter sub-select are used very often. I was trying to implement a function in Oracle to get my parameters. This works very fine as long as there is just 1 row per parameter. When I want to use it in "IN-Statements", it won't work because functions just return a single value.
--WORKS
SELECT * FROM tablex
WHERE code = (f_get_param('A_03'));
--DOES NOT WORK
SELECT * FROM tablex
WHERE code IN (f_get_param('A_04'));
Please note that I need it for plain SQL statements, so procedures won't work as they are just good for PL/SQL.
I would be really thankful for good ideas or help!
Use collections. Here you have an example http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html
Technically you can achieve using the function this way but doing this will cause index not to be used on code column on tablex and may affect performance .Using function index you can reduce performance impact
CREATE OR REPLACE FUNCTION f_get_param(p_value1 IN VARCHAR2,p_name1 in VARCHAR2) return NUMBER
DETERMINISTIC
IS
l_count NUMBER;
BEGIN
select count(1) into l_count from parameter_table where p_value =p_value1
and p_name=p_name1;
if l_count > 0
then
return 1;
else
return 0;
end if;
end f_get_param;
AND use the select statement like this
SELECT * FROM tablex
WHERE f_get_param(code,'A_04')=1;
EDIT 1:-
Also to reduce the performance impact in database 10.2 and greater If the parameter_table is static you can use the DETERMINISTIC clause in the Function to say that the function returns the same value if called with same parameters every time
Please find the link on the article about using functions in SELECT statement
--DOES NOT WORK
SELECT * FROM tablex
WHERE code IN (f_get_param('A_04'));
-- Try this
SELECT * FROM tablex
WHERE code IN (select * from TABLE(f_get_param('A_04')));
You have to "CAST" a collection onto SQL TABLE.
Also when you use cast you can also use inner joint:
SELECT * FROM tablex join TABLE(f_get_param('A_04') using (code);
I think - generally - your problem is called "Dynamic where clause". Try to search some articles about it on AskTom.
I think the actual solution to your problem is to simply join the two tables and create the appropriate indexes rather than invoking a PL/SQL function at all:
SELECT x.* FROM tablex x, parameter_table p
WHERE x.code = p.p_value
AND p.p_name LIKE '%A_04%';
Note that you also have a semantic error in your LIKE clause. You're not using the % sign therefore your LIKE 'A_04' is just the same as = 'A_04'

Resources