I have a problem when try extract ddl for sequence using this function in this query:
select dbms_metadata.get_dependent_ddl('SEQUENCE', base_object_name) from dual;
base_object_name - name of trigger, that use sequences.
Result: ora-31604 invalid name parameter NAME "BASE_OBJECT_NAME" for OBJECT_TYPE 'SEQUENCE'
For example when I execute this query:
select dbms_metadata.get_dependent_ddl('INDEX', base_table_name) from dual;
in result I have indexes for specified table.
Please, help, how to extract sequence ddl using get_dependent_ddl() function?
Sequences are not dependent on tables, therefore you need to use select dbms_metadata.get_ddl('SEQUENCE', 'SEQ_NAME') from dual; to retrieve its ddl.
A sequence is not dependent on a trigger. It is a separate object that requires no other object in order to exist. Use the GET_DDL subprogram on DBMS_METADATA instead:
select dbms_meta_data.get_ddl('SEQUENCE',sequence_name) from dual
Related
I'd like to ask how to pass an array of strings as parameter in Peoplesoft.
In Oracle query, I can do that like the following
SELECT EMP_ID, EMP_NAME
from EMPLOYEE
where EMP_ID in (select regexp_substr(:empid,'[^,]+', 1, level) from dual connect by regexp_substr(:empid, '[^,]+', 1, level) is not null)
And pass in parameter value as
E001,E002,E003,...
But in Peoplesoft Query Manager, when I create the in criteria to a subquery, it does not allow from clause in it.
Another alternative that I try is using Prompt and then pass the value to it, so the query becomes like:
SELECT EMP_ID, EMP_NAME
from EMPLOYEE
where EMP_ID in (:1)
But this also does not work.
So how do I do this?
I can't tell if you are asking about doing this in ps query manager or in peoplecode.
Maybe use older methods, like populating a table first, and joining to that table. Maybe use a "With" clause.
Please share what you ended up using, to accomplish your goal.
Trying to generalize the SQL what splits a string/varchar into records. Here is the working SQL:
SELECT test.* FROM test JOIN (
SELECT level nbr, REGEXP_SUBSTR('1,3', '(.*?)(,|$)', 1, level, NULL, 1) value
FROM dual CONNECT BY level <= REGEXP_COUNT('1,3', ',')+1 ORDER BY level
) requested ON test.id=requested.value
What I mean by generalizing is; moving the recurring SQL (in this case the bit between the parenthesis's from the working SQL above) to a procedure/function so it can be reused. In this case I'm trying to find a way to insert a generated inner select statement. This is how the generalized SQL may look like:
SELECT t.* FROM table t JOIN (<GENERATED_INNER_SELECT>) my ON t.x=my.x;
However I didn't succeed yet, I tried tho but calling my function to generate the inner select statement directly resulted in:
ORA-00900: invalid SQL statement
And using the function in the generalized SQL resulted in:
ORA-00907: missing right parenthesis
None of these errors make any sense to me in this context.
Perhaps you can help? check out the full case on dbfiddle.
If you generate a SQL fragment to use as a subquery then the overall statement that embeds that as a subquery would have to be executed dynamically too.
It would be simpler to have the function actually doing the split itself, and returning a collection - as a schema-level collection type:
CREATE TYPE T_NUMBERS AS TABLE OF NUMBER
/
CREATE OR REPLACE FUNCTION split(p_string VARCHAR2, p_seperator VARCHAR2 DEFAULT ',')
RETURN T_NUMBERS AS
L_NUMBERS T_NUMBERS;
BEGIN
SELECT REGEXP_SUBSTR(p_string, '(.*?)(,|$)', 1, level, NULL, 1)
BULK COLLECT INTO L_NUMBERS
FROM dual
CONNECT BY level <= REGEXP_COUNT(p_string, ',')+1;
RETURN L_NUMBERS;
END split;
/
SELECT * FROM TEST
WHERE id MEMBER OF (split('1,3'))
/
ID NAM
---------- ---
1 foo
3 foe
or if you prefer the table collection expression approach:
SELECT t.*
FROM TABLE(split('1,3')) tmp
JOIN test t ON t.id = tmp.column_value;
It would be even simpler if the query could be called with a collection of numbers in the first place, but without seeing how the call is being made - and the string generated - it's hard to say exactly how you'd need to change that. You could even use a built-in collection type then, instead of having to define your own:
SELECT t.*
FROM TABLE(SYS.ODCINUMBERLIST(1,3)) tmp
JOIN test t ON t.id = tmp.column_value;
but it relies on the caller being able to pass the numbers in rather than a string (note the lack of single quotes...)
What I want to achieve (if it is possible from SQL Developer) is that when I execute the script it do the following:
Run a SELECT statement that will return a list of IDs. Approx 270 records.
I need to use each of those IDs individually in another SELECT statement (in the WHERE clause) which will return some records. A few of this could result in over 17,000 records and some can be one.
Then each result from the second SELECT I want it to be exported to an excel or csv file into a folder at my pc.
I have both 'Select' ready but I don't know how to loop over the results of the first to grab each ID and use it in the second one. Also I don't know how to export automatically from the code.
You can use GROUP BY clause.
read more here:
http://docs.oracle.com/javadb/10.6.2.1/ref/rrefsqlj32654.html
If the first SELECT returns you IDs only, and that's all you need for your second SELECT, just use IN clause providing your first SELECT query for the second one.
Example:
-- Your second select
SELECT
col1
,col2
,col3
,col4
FROM
second_table
WHERE
some_foreign_id IN (
-- Your first select
SELECT
id
FROM
first_table
WHERE
some_conditions...
)
In my opinion don't use PLSQL for this. In PLSQL the only way you can get an output of this by using a REFCURSOR (unless you dont use UTIL File package to do it). A simple SELECT WITH JOIN condition will suffice your requirement.
Test illustration
SELECT A.* FROM TABLE_A A, TABLE_B
WHERE A.COMMON_COLUMN = B.COMMON_COLUMN;
Hope this helped you in same way
I've created an anonymous PLSQL block to test and I'm running into an issue with the formatting.
set serveroutput ON
BEGIN
FOR I IN (SELECT DISTINCT do.SUBOBJECT_NAME from dba_objects do WHERE do.object_name='MY_TABLE' AND do.OBJECT_TYPE='TABLE PARTITION') LOOP
dbms_output.put_line(I.subobject_name);
SELECT
t.field
INTO
some_var
FROM
MY_TABLE PARTITION(I.subobject_name) t;
END LOOP;
END;
However I get several compilation errors, which I believe are related to the fact that I.subobject_name is a string. I believe the PARTITION function wants an actual partition symbol(proper term for this?), but I can't give it in this loop.
Is there any kind of casting function that can perform what I'm looking for?
Partition IS NOT A FUNCTION. Partition is keyword
In your context your whole statement is static , thus you CANNOT pass partition name into it; partition name must be specified at compile time.
You can re-create your statement dynamically and then pass partition name in the loop -
a-la you are doing it. Just make sure you will concatenate string and not use bind variables, or your statement at run time won't be parsed and won't run.
Name for the symbol is table partition
I need a little stored procedure to do the following logic?
procedure_name(seq_name IN varchar2(50), block_count IN int, return_ids OUT)
loop from 1 to block_count
return_ids := select 'seq_name'||.nextVal from dual;
end loop
return return_ids
Basically what I want to do is have a stored procedure that lets me pass in a sequence name, how many IDs I need and return to me the generated listed of IDs that I can use in JAVA. The reason to do this for me is to return a list of IDs that I can use in JAVA and no one else is using those sequence IDs. Where they will be used in some other bulk inserts later down the line. In essence, reserve a block of sequence IDs.
Here is one way to return an array from PL/SQL procedure.
Create a collection type of numbers, initialize it in your procedure and populate it with numbers to return. For example:
create or replace type narray as table of number;
create or replace procedure get_seq_ids(seq_name in varchar2,
block_count in number, return_ids out narray)
as
begin
return_ids := narray();
return_ids.extend(block_count);
for i in 1 .. block_count
loop
execute immediate 'select ' || seq_name || '.nextval from dual'
into return_ids(i);
end loop;
end;
/
I'd be concerned over the logic that requires IDs to be generated before records are inserted into the database.
Alternatively you may want to consider inserting rows first, selecting the ids from the rows, and then using an update statement to do your bulk operation. This however is still not as preferable as having the Java code not depend on ids until after the actual information is ready to be inserted.
You can push your information into XML (or any other data format your database can understand) and then call a stored procedure to do the bulk inserts.
Another option may be to use the RETURNING clause to return the sequence values automatically after the insert.
IMHO, the best thing you can do is just referencing sequence_name.nextval right in your INSERT INTO, in the VALUES clause.
You said you want to avoid others using the same IDs. Referencing this site:
The sequence (or Oracle, for that matter) ensures that no other session or other call to nextval within the same session gets the same number from the sequence.
So, the uniqueness of a sequence' numbers are guaranteed in Oracle.
Here's what I do for the Java application I support (which also uses bulk inserts into deeply hierarchical tables)
PROCEDURE get_nextvals
(
p_values OUT SYS_REFCURSOR,
p_count IN PLS_INTEGER
)
IS
-- return the next p_count values from the PK sequence
BEGIN
OPEN p_values FOR
SELECT
<schema>.<sequence>.nextval
FROM
dual
CONNECT BY
LEVEL <= p_count
;
END;
It was easier to just pass a cursor out to java than having the app use a table type defined in the DB.