Can't alter password - sql

I am trying to alter the password of a user in plsql:
DECLARE
BEGIN
ALTER USER BOB IDENTIFIED BY PASS123;
END;
I keep getting the error when I create it and cannot make it out what it wrong:
ORA-06550: line 4, column 1: PLS-00103: Encountered the symbol "ALTER"
when expecting one of the following: ( begin case declare exit for
goto if loop mod null pragma raise return select update while with
<< continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge

According to doc
Only dynamic SQL can execute the following types of statements within
PL/SQL program units:
Data definition language (DDL) statements such as CREATE, DROP, GRANT,
and REVOKE
Session control language (SCL) statements such as ALTER SESSION and
SET ROLE
The TABLE clause in the SELECT statem
DECLARE
BEGIN
EXECUTE IMMEDIATE 'ALTER USER BOB IDENTIFIED BY PASS123';
END;

You can use DDL statements (alter, create, grant etc) without begin-end block.
ALTER USER BOB IDENTIFIED BY PASS123;

Related

Why am I getting this error? PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:

I am getting this error
Compilation failed, line 2 (11:52:47) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PLS-00103: Encountered the symbol "CREATE" when expecting one of the
following: ( begin case declare exit for goto if loop mod null pragma
raise return select update while with << continue close current
delete fetch lock insert open rollback savepoint set sql execute
commit forall merge pipe purge json_exists json_value json_query
json_object json_array
Code:
create or replace trigger "GDS_CLIENT_T1"
BEFORE
insert or update or delete on GDS_CLIENT
for each row
begin
create or replace trigger "client insert"
before
insert on "Identify Client"
for each row
begin
select nv1(max(id),0)+1 into :NEW_ID FROM IDENTIFY CLIENT
end;
CREATE OR REPLACE TRIGGER is a DDL command that requires a full specification of the trigger to create; in your case, your first command has not ended:
create or replace trigger "GDS_CLIENT_T1"
BEFORE
insert or update or delete on GDS_CLIENT
for each row
begin
At this point it is expected that you will finish the definition of the GDS_CLIENT_T1 trigger; but instead, you have create or replace trigger which is not valid PL/SQL.

Does anyone know why this trigger is not working?

create or replace NONEDITIONABLE TRIGGER SetNapomena
BEFORE INSERT
ON stavkafakture
FOR EACH ROW
DECLARE
V_napomena VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'ALTER TRIGGER zabranjeno DISABLE';
SELECT napomena INTO V_napomena
FROM faktura
WHERE brojfakture =:NEW.brojfakture;
:NEW.napomena := V_napomena;
EXECUTE IMMEDIATE 'ALTER TRIGGER zabranjeno ENABLE';
END;
When I insert into a table (in this case stavkafakture) I get this error:
Cannot commit in a trigger
I did some research and added Pragma Autonomous Transaction and commit, but after adding them I try to insert a row in the table it loads forever and never works.
It stays in load forever.
Does anyone know why?
In Oracle DDL statement like CREATE, ALTER, DROP generate an explicit commit.
IE if you issue this kind of statement this does not requires a COMMIT nor a ROLLBACK :
CREATE TABLE MyTable(MyField NUMBER);
This will create the MyTable table and cannot be ROLLBACK.
This is a limitation of Oracle that other RDBMS like PostreSQL doesn't have.

Oracle: Setting Session Parameters in Packages and Procedures

I'm a SQL Server DBA currently getting up to speed on Oracle. I'm trying to create something very similar to sp_WhoIsActive for SQL Server but for Oracle without reinventing the wheel. Essentially all I'm doing is selecting some values from v$session and inserting them into a table (poor man's ASH/AWR).
It would seem that in Oracle 12.1, there's a bug when querying dictionary views where it can take forever due to bad parsing logic (Bug 22225899 : SLOW PARSE FOR COMPLEX QUERY). The work-around is to set a session parameter:
alter session set "_optimizer_squ_bottomup"=false;
In T-SQL, I could very easily execute a stored procedure in-session and set this variable at runtime. However in Oracle, it wouldn't seem thats the case.
Sample Code:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(
v_temp NUMBER :=1
) IS
BEGIN
alter session set "_optimizer_squ_bottomup"=false;
INSERT INTO SY_DB_ACTIVITY
SELECT
<fields>
FROM
v$session;
commit;
When I run this, I get the error:
"PLS-00103: Encountered symbol 'ALTER' when expecting one of the following..."
Right now, the only way I know how to do this is via a utility like SQL Plus that initiates an interactive user session. Can anyone give me some direction as to how Oracle handles this situation? I'd like to bundle this up into a SP or a Package and then call it from Oracle Scheduler.
Hre is a simple example how to execute alter session inside of the procedure:
CREATE PROCEDURE SP_DB_ACTIVITY IS
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
END;
/
Here is the way you can combine that with your select and insert statement:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
SELECT 1
INTO v_Id
FROM dual;
INSERT INTO SY_DB_ACTIVITY (id) VALUES(v_Id);
END SP_DB_ACTIVITY;
/
Here is a small DEMO where you can see what will procedure do when you call it and how you can call it. Also, in this example you are calling procedure with and IN parameter. So you can use that parameter for something and in the example above is the procedure without any parameters...
You can also, of course, insert into table directly:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
INSERT INTO SY_DB_ACTIVITY(id)
select 1
from dual;
END SP_DB_ACTIVITY;
/

Why inside of a trigger the code before raise_application_error isn't executed?

IF I create this trigger, then the error is raised when drop or truncate is used on tables, but there is nothing inserted into logTable, but if I delete RAISE_APPLICATION_ERROR... then the values are inserted into logTable, but the drop/truncate are executed too. Why? How can I avoid drop/truncate on Schema (If I use instead of trigger, it is fired only if owner of the schema is dropping/truncating something).
CREATE OR REPLACE TRIGGER trigger_name
BEFORE DROP OR TRUNCATE ON DATABASE
DECLARE
username varchar2(100);
BEGIN
IF ora_dict_obj_owner = 'MySchema' THEN
select user INTO username from dual;
INSERT INTO logTable VALUES(username , SYSDATE);
RAISE_APPLICATION_ERROR (-20001,'ERROR, YOU CAN NOT DELETE THIS!!');
END IF;
END;
According to the documentation:
Statement-Level Atomicity
Oracle Database supports statement-level atomicity, which means that a SQL statement is an atomic unit of work
and either completely succeeds or completely fails.
A successful statement is different from a committed transaction. A
single SQL statement executes successfully if the database parses and
runs it without error as an atomic unit, as when all rows are changed
in a multirow update.
If a SQL statement causes an error during execution, then it is not
successful and so all effects of the statement are rolled back. This
operation is a statement-level rollback.
The procedure is a PL/SQL statement, it is atomic, if you raise an error within the procedure, then the whole procedure fails and Oracle performs a rollback of all the changes done by this procedure.
But you can create a procedure with AUTONOMOUS_TRANSACTION Pragma in order to bypass this behaviour, in this way:
CREATE TABLE logtable(
username varchar2(200),
log_date date
);
CREATE OR REPLACE PROCEDURE log_message( username varchar2 ) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO logtable( username, log_date ) VALUES ( username, sysdate );
COMMIT;
END;
/
CREATE OR REPLACE TRIGGER trigger_name
BEFORE DROP OR TRUNCATE ON DATABASE
DECLARE
username varchar2(100);
BEGIN
IF ora_dict_obj_owner = 'TEST' THEN
log_message( user );
RAISE_APPLICATION_ERROR (-20001,'ERROR, YOU CAN NOT DELETE THIS!!');
END IF;
END;
And now:
drop table table1;
ORA-00604: error occurred at recursive SQL level 1
ORA-20001: ERROR, YOU CAN NOT DELETE THIS!!
ORA-06512: at line 6
00604. 00000 - "error occurred at recursive SQL level %s"
*Cause: An error occurred while processing a recursive SQL statement
(a statement applying to internal dictionary tables).
*Action: If the situation described in the next error on the stack
can be corrected, do so; otherwise contact Oracle Support.
select * from logtable;
USERNAME LOG_DATE
-------- -------------------
TEST 2018-04-27 00:16:34

Can not have CREATE TABLE inside if else

When I run this query
DECLARE
num NUMBER;
BEGIN
SELECT COUNT(*) INTO num FROM user_all_tables WHERE TABLE_NAME=upper('DatabaseScriptLog')
;
IF num < 1 THEN
CREATE TABLE DatabaseScriptLog
(ScriptIdentifier VARCHAR(100) NOT NULL,
ScriptType VARCHAR(50),
StartDate TIMESTAMP,
EndDate TIMESTAMP,
PRIMARY KEY (ScriptIdentifier)
);
END IF;
END;
When execute the above, I got the following:
PLS-00103: Encountered the symbol
"CREATE" when expecting one of the
following:
begin case declare exit for goto if
loop mod null pragma raise return
select update while with << close current delete
fetch lock insert open rollback
savepoint set sql execute commit
forall merge pipe
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
You cannot run DDL statements like that. You need to use dynamic SQL (EXECUTE IMMEDIATE).
IF num < 1 THEN
EXECUTE IMMEDIATE 'CREATE TABLE DatabaseScriptLog (ScriptIdentifier VARCHAR(100) NOT NULL, ScriptType VARCHAR(50), StartDate TIMESTAMP, EndDate TIMESTAMP, PRIMARY KEY (ScriptIdentifier))'
END IF;
You cannot do this like you could in SQLServer. You need to execute the create code through a stored procedure that is already in the proper schema. You pass the create code as a parameter and the stored procedure that has the correct privileges does it for you.
I use a version script that updates the schema to the latest by running schema altering operations separated by if-then clauses to check what version the db is at. After altering it increments the version so that the next if statements test passes and so on. If you are up to date and run the script the ifs skip all altering code. If your db is at version 46 and you run the script which has all changes up to 50, you execute only the blocks that represent versions 47-50.
You could execute immediate but would need elevated privileges which I would not recommend.
Hope this helps.