I want to use the REPLACE function in the Where clause to replace a character that I put into a input box. For example if I input R123;R321 I want it to change my input to R123','R321.
Example of my query:
Select
order_no
From
order
Where
order_no in ('&Order_No')
I input the data with this box:
Any help would be appreciated, or if there is some other way to do it without the REPLACE function.
That won't work like this, I'm afraid. You'll have to split input value into rows, e.g.
SQL> select deptno, ename
2 from emp
3 where deptno in (select regexp_substr('&&deptnos', '[^;]+', 1, level)
4 from dual
5 connect by level <= regexp_count('&&deptnos', ';') + 1
6 )
7 order by deptno, ename;
Enter value for deptnos: 10;20
DEPTNO ENAME
---------- ----------
10 CLARK
10 KING
10 MILLER
20 ADAMS
20 FORD
20 JONES
20 SCOTT
20 SMITH
8 rows selected.
SQL>
Related
I need to write a single sql or pl/sql to accomplish the following:
select value1 from table1;
-----------------------------
99
select value2 from table2;
------------------------------
120
I need to find out 99 is what percentage of 120?
Based on the formula P = X1/X2 * 100 the result will be 82.5%
Thanks for your help.
It'll work if both tables have a single row (that's what your examples suggest). I used CTE instead of your "real" tables, so query you might be interested in begins at line #7.
SQL> with
2 table1 (value1) as
3 (select 99 from dual),
4 table2 (value2) as
5 (select 120 from dual)
6 --
7 select a.value1 / b.value2 * 100 as result
8 from table1 a cross join table2 b;
RESULT
----------
82,5
SQL>
As you stated that PL/SQL could be an option, consider creating a function:
SQL> create or replace function f_pct(par_1 in number, par_2 in number)
2 return number
3 is
4 begin
5 return par_1 / par_2 * 100;
6 exception
7 when others then
8 -- in case of e.g. PAR_2 = 0
9 return null;
10 end;
11 /
Function created.
Let's test it:
SQL> select ename, sal, comm, f_pct(comm, sal) result
2 from emp;
ENAME SAL COMM RESULT
---------- ---------- ---------- ----------
SMITH 800
ALLEN 1600 300 18,75
WARD 1250 500 40
JONES 2975
MARTIN 1250 1400 112
BLAKE 2850
<snip>
I'm using a DB 'A' to output a list of numbers :
123455
123456
123457
And I'm looking to build a dynamic statement to look into a DB 'B' with those results as a filter
a. Build an array with the values from DB 'A'
SELECT * FROM my_table
WHERE number in &array;
How can I achieve this ?
The DB 'B' is an Oracle DB.
Thanks
Hm. Looks like your "background" is not Oracle, because there are no "DB"s there. I mean, there are, but not in a context you're using them. If "DB" stands for a "Database", to me it looks as if you're actually talking about tables here.
Also, I don't understand what
The DB 'B' is in PLSQL means.
If "database" is a table, how is it in PL/SQL?
Anyway, to get you started: I'm fetching some data from Scott's EMP and DEPT tables. For collections, I'm using Oracle's built-in types.
These are employees in departments 10 and 20:
SQL> select deptno, ename
2 from emp
3 where deptno in (10, 20)
4 order by deptno, ename;
DEPTNO ENAME
---------- ----------
10 CLARK
10 KING
10 MILLER
20 ADAMS
20 FORD
20 JONES
20 SCOTT
20 SMITH
8 rows selected.
PL/SQL procedure which does something with them (the way I understood the question):
SQL> declare
2 l_a sys.odcinumberlist;
3 l_b sys.odcivarchar2list;
4 begin
5 select deptno
6 bulk collect into l_a
7 from dept
8 where deptno in (10, 20);
9
10 select ename
11 bulk collect into l_b
12 from emp
13 where deptno in (select * from table(l_a))
14 order by ename;
15
16 for i in l_b.first .. l_b.last loop
17 dbms_output.put_line(l_b(i));
18 end loop;
19 end;
20 /
ADAMS
CLARK
FORD
JONES
KING
MILLER
SCOTT
SMITH
PL/SQL procedure successfully completed.
SQL>
Lines #1 - 3 - declaration section
lines #5 - 8 - inserting values (departments) into l_a collection
Lines #10 - 14 - inserting values (employees) into l_b collection, based on values stored in l_a
Lines #16 - 18 - displaying contents of l_b
See if it helps.
[EDIT] After seeing your comment: as far as I can tell, you can't do what you wanted, not as simple as you'd want it to. This is how it works - you enter a comma-separated values as a parameter (that's your "array"), split it into rows and use the result as a subquery:
SQL> SELECT *
2 FROM dept
3 WHERE deptno IN ( SELECT REGEXP_SUBSTR ( '&&par_depts',
4 '[^,]+',
5 1,
6 LEVEL)
7 FROM DUAL
8 CONNECT BY LEVEL <= REGEXP_COUNT ( '&&par_depts', ',') + 1);
Enter value for par_depts: 10,20
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
SQL>
This is a SQL*Plus example; you'll probably have to substitute '&&par_depts' with :par_depts (depending on a tool you use).
Use the MEMBER operator.
First create a collection type in SQL:
CREATE TYPE int_list IS TABLE OF INT;
Then just use it in an SQL statement:
SELECT *
FROM my_table
WHERE value MEMBER OF int_list(123455, 123456, 123457);
Which, for the sample data:
CREATE TABLE my_table ( id, value ) AS
SELECT LEVEL, 123453 + LEVEL FROM DUAL CONNECT BY LEVEL <= 5;
Outputs:
ID
VALUE
2
123455
3
123456
4
123457
If you want it in PL/SQL then:
DECLARE
items int_list := int_list(123455, 123456, 123457);
BEGIN
FOR row IN (
SELECT *
FROM my_table
WHERE value MEMBER OF items
)
LOOP
DBMS_OUTPUT.PUT_LINE( row.id || ', ' || row.value );
END LOOP;
END;
/
Which, for the same data, outputs:
2, 123455
3, 123456
4, 123457
db<>fiddle here
However, if you just want to connect two databases then setup a database link.
From front end User will enter (multiple) employee number as (123,456,789) to search in the application. The way User enters the
employee numbers is pre-defined like above.
This value has to be searched in a Oracle database table in a PL/SQL package.
I have coded like below to format the entered value so that it can be searched in the SQL WHERE condition.
lv_where := REPLACE( REPLACE( REPLACE( '(123,456,789)', ',', ''',''' ), '(', '(''') , ')', ''')')
Output is : ('123','456','789')
Is there a better way?
you can use regexp_replace
regexp_replace('(123,456,789)','([[:digit:]]+)','''\1''')
Result:
('123','456','789')
Unless it is dynamic SQL, such a lv_where won't work. I'd suggest you to split entered values into rows and use them in your query.
In the following example, par_emp represents value entered by user. Basically, what you need begins at line #3.
SQL> with test (par_emp) as
2 (select '(10,20,30)' from dual)
3 select deptno, ename
4 from emp
5 where deptno in (select regexp_substr(replace(replace(par_emp, '(', ''), ')', ''), '[^,]+', 1, level)
6 from test
7 connect by level <= regexp_count(par_emp, ',') + 1
8 )
9 order by deptno;
DEPTNO ENAME
---------- ----------
10 CLARK
10 KING
10 MILLER
20 JONES
20 FORD
20 ADAMS
20 SMITH
20 SCOTT
30 WARD
30 TURNER
30 ALLEN
30 JAMES
30 BLAKE
30 MARTIN
14 rows selected.
SQL>
I have a case in which I need to order the query result in a customized order like the following :
the DEPARTEMENT_ID needs to be in this order ( 10 then 50 then 20 )
is there a way to get this result ?
You could use CASE expression in the ORDER BY clause.
I answered a similar question here, https://stackoverflow.com/a/26033176/3989608, you could just tweak it to have your customized conditions in the CASE expression.
For example,
SQL> SELECT ename,
2 deptno
3 FROM emp
4 ORDER BY
5 CASE deptno
6 WHEN 20 THEN 1
7 WHEN 10 THEN 2
8 WHEN 30 THEN 3
9 END
10 /
ENAME DEPTNO
---------- ----------
SMITH 20
FORD 20
ADAMS 20
JONES 20
SCOTT 20
CLARK 10
KING 10
MILLER 10
ALLEN 30
TURNER 30
WARD 30
MARTIN 30
JAMES 30
BLAKE 30
14 rows selected.
SQL>
One way you can do it is to have an other column DISPLAY_ORDER having serial number data in the order that you want it.
so the sql will be
select JOB_ID, DEPARTMENT_ID
from EMPLOYEES
order by DISPLAY_ORDER;
You can use the DECODE to accomplish this.
SELECT JOB_ID,DEPARTMENT_ID
FROM YOURTABLE
ORDER BY DECODE(DEPARTEMENT_ID, 10, 1, 50, 2, 20, 3,4)
Refer to these threads below for more information.
Custom Order in Oracle SQL
DECODE
What is the difference between ROWNUM and ROW_NUMBER ?
ROWNUM is a "pseudocolumn" that assigns a number to each row returned by a query:
SQL> select rownum, ename, deptno
2 from emp;
ROWNUM ENAME DEPTNO
---------- ---------- ----------
1 SMITH 99
2 ALLEN 30
3 WARD 30
4 JONES 20
5 MARTIN 30
6 BLAKE 30
7 CLARK 10
8 SCOTT 20
9 KING 10
10 TURNER 30
11 FORD 20
12 MILLER 10
ROW_NUMBER is an analytic function that assigns a number to each row according to its ordering within a group of rows:
SQL> select ename, deptno, row_number() over (partition by deptno order by ename) rn
2 from emp;
ENAME DEPTNO RN
---------- ---------- ----------
CLARK 10 1
KING 10 2
MILLER 10 3
FORD 20 1
JONES 20 2
SCOTT 20 3
ALLEN 30 1
BLAKE 30 2
MARTIN 30 3
TURNER 30 4
WARD 30 5
SMITH 99 1
From a little reading, ROWNUM is a value automatically assigned by Oracle to a rowset (prior to ORDER BY being evaluated, so don't ever ORDER BY ROWNUM or use a WHERE ROWNUM < 10 with an ORDER BY).
ROW_NUMBER() appears to be a function for assigning row numbers to a result set returned by a subquery or partition.
Apart from the other differences mentioned in answers, you should also consider performance. There is a non-authoritative but very interesting report here, comparing various means of pagination, among which the use of ROWNUM compared to ROW_NUMBER() OVER():
http://www.inf.unideb.hu/~gabora/pagination/results.html
rownum is a pseudocolumn which can be added to any select query, to number the rows returned (starting with 1). They are ordered according to when they were identified as being part of the final result set. (#ref)
row_number is an analytic's function, which can be used to number the rows returned by the query in an order mandated by the row_number() function.
Rownum starts with 1 ..increases after condition evaluated results to true .
Hence rownum >=1 returns all rows in table