Regenerate all sequences in db (oracle) - oracle

Good day. I have a very specific task: regenerate all sequences in database. There is a 400+ tables in it, so I can't do it by hands.
Can somebody help me to do it?
Thanks a lot..

Please note this is highly dangerous. You may very well make mistakes. Run the select first to check what you're about to do and create a table of the select so you can re-create the synonyms manually later if you need to.
Using all_synonyms or dba_synonyms instead of user_synonyms may result in dropping system synonyms do not do this if you want your database to work afterwards
I'd also recommend testing the code on 1 test synonym you create to ensure that it does exactly what you want.
Plus I don't really see the point of doing this at all? If the synonyms are there why do you need to re-generate them? Or is this being done on another server? If so add #server_name after user_synonyms and remove the drop.
begin
for xx in ( select * from user_sequences ) loop
execute immediate 'drop sequence ' || xx.sequence_name;
execute immediate 'create sequence ' || xx.sequence_name
|| ' start with ' || xx.min_value
|| ' ends with ' || xx.max_value
|| case when xx.cycle_flag = 'N' then ' nocycle '
else ' cycle ' end
|| case when xx.cache_size = 0 then ' nocache '
else ' cache ' end || xx.cache_size
|| case when xx.order_flag = 'N' then ' noorder '
else ' order ' end
;
end loop;
end;

Related

Oracle: Dynamic SQL with Update not working

I have this instruction
UPDATE TABLE1
SET INC =
(select INC from TABLE2
WHERE KEY = 'KEY_VALUE1'
FETCH FIRST 1 ROW ONLY);
This working fine if i run from sqlPlus or if I use in PLSQL but, if I using in Dynamic SQL, not working
sqlStmt:= 'UPDATE TABLE1'
|| 'SET INC = '
|| '(select INC from TABLE2 '
|| 'WHERE KEY = ''' || v_key_value || ''' '
|| 'FETCH FIRST 1 ROW ONLY); ';
BEGIN
EXECUTE IMMEDIATE sqlStmt;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('{"errorcode":"' || SQLERRM);
ROLLBACK;
END;
This instruction return this error:
{"errorcode":"ORA-00933: comando SQL terminato erroneamente
Someone can you help me?
Regards,
Marco
You don't want to have a semicolon at the end of the string you are building and passing to execute immediate.
It's not the cause of your error. But it would be much kinder to the database to write this using bind variables rather than concatenating literals. Of course, since there is no reason to be using dynamic SQL for this sort of update statement, I'm guessing your actual use case is different and that you are actually using bind variables and/or there is actually a reason why bind variables aren't an option.

Incremental commit while using execute immediate when table name and column name are dynamic

I've the need to update a few tables. The tables and columns to be updated will be fetched from another table. So my update statement in the procedure looks like this
EXECUTE IMMEDIATE
'UPDATE '
|| In_owner
|| '.'
|| In_table_name
|| ' upd_tbl '
|| ' SET '
|| In_sql_stmt_col_list
|| ' WHERE '
|| In_sql_stmt_where_clause;
As you can see, table name, the set clause and the where clause are all dynamically built. What I want to do now is perform a commit after every n records. How do I do that?
Assuming that you are able to recognize updated rows from not updated you can try to fit the below sample to your case.
The nbatchsize is number of rows that you want to commit each time.
The i is the number of rows that were updated in the last loop.
The updates are looped by while until number of updated rows is lower than your nbatchsize.
Of course it would only work when you are able to recognize already updated rows from not updated ones.
You can use for that In_sql_stmt_col_list if you don't have any lastupdateon column.
declare
nbatchsize number := 10;
i number := nbatchsize;
begin
while i >= nbatchsize
loop
EXECUTE IMMEDIATE '
update
Table
set lastupdateon = sysdate
where
lastupdateon < sysdate -1
and rownum <= :1 ' using nbatchsize;
i := sql%rowcount;
commit;
dbms_output.put_line(i);
end loop;
end;

Replace character in all columns using Oracle Data Modeler

Is it possible to simply change character in name of tables columns? At the moment columns have seperator - and I want to change it with underscore (_) . Is it possible to do it easy with 1 click or should I go through all tables and change it by hand?
I don't know oracle SQL data modeler. If you have access to SQL*Plus or another developer tool, you can run script, it will change all columns of tables in your schema:
begin
for i in (select table_name, column_name from user_tab_columns) loop
if instr(i.column_name, 'A') > 0 then
execute immediate 'alter table ' || i.table_name || ' rename column ' ||
i.column_name || ' to ' || replace(i.column, 'A', 'B');
end if;
end loop;
end;
/
Here 'A' is symbol that you want to replace and 'B' - new symbol to use. But be careful, such scripts can be dangerous. Try it on test schema first.

Building some dynamic query select and display its output immediately in Oracle PL/SQL

in my actual job I need, very often, to read some tables and acting consequently, sometimes updating these data manually.
So I built a PL/SQL block that creates my SELECT statements (yes, with the "FOR UPDATE" clause, just commented).
As an example, this is just one of the queries I build:
phtr_QUERY := 'SELECT *
FROM ' || tabriabi_impianto || '.pdfhtr t
WHERE t.k_abi=''' || tabriabi_abi || ''' ';
if length(myNag) > 0 then
phtr_QUERY := phtr_QUERY || 'and t.ndg like ''%' || myNag || '%'' ';
end if;
if length(myPrat) > 0 then
phtr_QUERY := phtr_QUERY || ' and t.pratica like ''%' || myPrat || '%'' ';
end if;
phtr_QUERY := phtr_QUERY || crlf || ' order by 2 ';
phtr_QUERY := phtr_QUERY || crlf || '--for update';
phtr_QUERY := phtr_QUERY || crlf || ';';
Then I copy these statements from the Output window (obtained through the dbms_output.put_line) and paste it into a new SQL Window and executing it, obtaining the results in multiple tabs.
I was wondering if there is a better way, some commands that I can use just to have the (editable) results directly without the need of cut&paste...
TIA.
F.
A very horrifying/hackish way to do what you want would be to store the resulting query in a temporary table, afterwards you could do something like the process described here:
How can I use an SQL statement stored in a table as part of another statement?
Please Note: This is probably a bad idea.
select a.rowid, a.* from table_name a;
will open in edit mode in many tools.
I was wondering if there is a better way, some commands that I can use just to have the (editable) results directly without the need of cut&paste
You should understand that editing features are features of database tool you are using. When you insert, update or delete some record in the results grid this tool translates your actions into respective SQL statements and executes it on the fly.
As a kind of workaround I suggest you to create a stored procedure which takes some parameters as 'table name', 'where conditions' and then creates updateable database view. After execution of procedure and preparation of the view you can run "select ... for update" and work with returned data as you do it now.

Parameters on Execute Immediate Sentence (Inside a procedure)

I'm triyin to create a ORACLE USER from my User table inside a procedure. The problem is that I don't know how to call a specific column. I've tried with Camp.user.username and that stuff.
create or replace
PROCEDURE PR_USERPASS AS
BEGIN
UPDATE CAMP.USERS
SET USERNAME = (DBMS_RANDOM.string('x',15)), PASS = DBMS_RANDOM.string('x',12);
EXECUTE IMMEDIATE 'CREATE USER ' || USERNAME || ' IDENTIFIED BY ' || PASSWORD;
EXECUTE IMMEDIATE 'Grant connect to ' || USERNAME;
END PR_USERPASS;
Is there anyway to call that references in the same procedure?
Thank you in advance.
Use a cursor to loop through the Camp.Users table and access its columns. Your code would go something like this (untested):
create or replace
PROCEDURE PR_USERPASS AS
BEGIN
UPDATE CAMP.USERS
SET USERNAME = (DBMS_RANDOM.string('u',15)), PASS = DBMS_RANDOM.string('x',12);
FOR userRow IN (SELECT Username, Pass FROM Camp.Users) LOOP
EXECUTE IMMEDIATE 'CREATE USER ' || userRow.Username || ' IDENTIFIED BY ' || userRow.Pass;
EXECUTE IMMEDIATE 'GRANT CONNECT TO ' || userRow.Username;
END LOOP;
END PR_USERPASS;
Addendum: The original answer generated USERNAME as DBMS_Random.String('x', 15), which allows digits and numbers for the username and password. This caused trouble when the username began with a digit. The answer was changed to use DBMS_Random.String('u', 15) to generate only Oracle-acceptable username values. The password seemed to be OK with the leading digit.
If usernames beginning with a digit are wanted, just surround the username with double quotes:
EXECUTE IMMEDIATE 'CREATE USER "' || userRow.Username || '" IDENTIFIED BY ' || userRow.Pass;
EXECUTE IMMEDIATE 'GRANT CONNECT TO "' || userRow.Username || '"';
That said, I'm not sure if having non-standard usernames is such a good idea.
Documentation for DBMS_Random.String can be found here.

Resources