Use Query result in ALTER statement (Oracle) - sql

I am trying to create a script to update passwords for a large number of users listed in a given table.
alter user FOO identified by FOOWORD;
I can call the usernames via the following statement:
select owner from usertable_verson where rownum = 1
Is there a way to combine these two statements, so that the alter user command works for each result of the select command?
The eventual goal is to create a loop for each username in the selected column, and apply the password change to each.

you can do this via dynamic SQL
smth like this:
begin
for rc in (select owner from usertable_verson) loop
execute immediate 'alter user '||rc.owner||' identified by FOOWORD';
end loop;
end;

Related

How to run a query in 50 databases in postgres?

I have 50 databases.
All the table schema in all the databases are the same. If I have a new column to be added to one table, I will have to run 50 times to update in all databases. This is very difficult all the time.
Is there an editor for postgres where there is a way to execute a query in all databases?
Currently, I am using dbeaver. I have to change the connection all the time and execute the query. Please help.
Example: I had to alter a table by adding a column.
ALTER TABLE table-name ADD new-column-name column-definition;
It is very difficult to execute for 50 databases.
For executing this answer, you need to have dblink extension.
DO $$
DECLARE
i text;
BEGIN
FOR i in SELECT datname FROM pg_database
LOOP
EXECUTE 'select * from dblink(''host=localhost
user=postgres
password=postgres
dbname='||i||' port=5432'',''ALTER TABLE table-name ADD new-column-name column-definition'' ) tt(
updated text)'
END LOOP;
END $$

How to delete data from specified tables at once in oracle sql

I have more than 40 tables in RATOR_MONITORING schema for which the table name is starting from 'TEMP_'. I want to delete data from all such tables at once in a single query instead of using delete statement for each and every table. I dont even want to generate statements. I can create anonymous block if required but dont know how to do that. I tried below query but its not working.
Delete from RATOR_MONITORING_CONFIGURATION.'%TEMP_';
If you want to delete all the rows, then better use TRUNCATE, it will reset the high watermark. But remember, truncate is a DDL statement, and thus there will be an implicit commit; With DELETE you can commit manually after validation.
Although, I would not do that in a production environment. If it is something you are doing in test environment to build test data, then you could (ab)use EXECUTE IMMEDIATE.
For example, execute the following anonymous block as RATOR_MONITORING user:
DECLARE
v_sql VARCHAR2(100);
BEGIN
FOR i IN
(SELECT table_name FROM user_tables where table_name like 'TEMP%'
)
LOOP
v_sql := 'TRUNCATE TABLE '||i.table_name;
EXECUTE immediate v_sql;
END LOOP;
END;
/
By the way, using a good text editor, it won't take more than a minute to build DELETE/TRUNCATE statements and do it in pure SQL.

Drop a user that is created with a script in Oracle DB with the (%)

I am trying to drop a user that is created with a sql script that is pass the user with an argument with a PowerShell script each time the script is run. Example: "ZKOracle01", ZKOracle02, and so on.
I was hoping I could get something like this to work at the beginning of the script to clean up the old users.
DROP USER LIKE ZKOracle%;
I know I could just do this at the beginning or end of my sql script,
DROP USER ZKOracle01;
but I need the user to remain in the DB for at least 6 hours.
You could write a bit of dynamic SQL
BEGIN
FOR u IN (SELECT *
FROM dba_users
WHERE username LIKE 'ZKOracle%')
LOOP
EXECUTE IMMEDIATE 'DROP USER ' || u.username;
END LOOP;
END;
I'd probably extend that to add a bit of logging, at least writing out the list of usernames that you're dropping, but that should do what you want. Remember as well that DROP USER is DDL so it implicitly commits before and after the statement-- you cannot rollback your changes.
To show an example of this working (the user I created was not case sensitive)
SQL> ed
Wrote file afiedt.buf
1 begin
2 for u in (select * from dba_users where username like 'ZKORACLE%')
3 loop
4 execute immediate 'drop user ' || u.username;
5 dbms_output.put_line( 'Dropped user ' || u.username );
6 end loop;
7* end;
SQL> /
Dropped user ZKORACLE01
PL/SQL procedure successfully completed.

Allow only adding of column/table/view in Oracle SQL

Suppose I have a platform which allows users to enter some SQL queries and execute them.
DB is Oracle 11.2
Is there any way to limit users' operations to CREATE TABLE, CREATE VIEW and ALTER table ADD COLUMN?
The only way I see is to parse all user provided queries with the grammar for Oracle DB 11.2. But this way is a very tedious one since there is no complete grammar in a free access (at least I couldn't find one) and implementing one will take days, if not weeks.
Grant CREATE TABLE and CREATE VIEW privileges.
For ALTER TABLE, to limit just ADD COLUMN, it's possible to create procedure and grant EXECUTE:
create or replace add_column( tableName varchar2, columnDefinition varchar2 )
as
execute immediate 'alter table '|| tableName || ' add column ' || columnDefinition;
end;
/
(not tested)
and
GRANT EXECUTE on ADD_COLUMN to user2;

pgSQL, dynamic drop tables statement

i want to dynamically delete some tables from database. I select them first, and then i am trying to use delete statement but it doesn't works.
tmp TEXT;
FOR tmp IN SELECT names from Garbage
LOOP
DROP TABLE tmp;
END LOOP;
but unfortuntly i got errors at drop statement. It always trying to delete table "tmp" instead of deleting the value of tmp(which are some strings like "table1" "table2").
You will need a dynamic query to be executed. To do that, you need to construct your query and call EXECUTE:
DECLARE
tmp TEXT;
...
BEGIN
...
FOR tmp IN SELECT names FROM Garbage
LOOP
EXECUTE 'DROP TABLE ' || quote_ident(tmp);
END LOOP;
...
Notice that I used quote_ident to escape the name properly, it is better and safer. But, if you created a table, let's say named MyTable but didn't quoted (double-quotes) it on creation time, PostgreSQL also store its name as mytable, so quote_ident('MyTable') will generate "MyTable" which doesn't exists, you should take care of it (e.g. always use the lowercase names or always quote your IDs).