DBMS access denied when using DBMS - oracle12c

As my title. I'm in trouble with this error. My code below:
create or replace PROCEDURE TEST(
P_CONTRACT VARCHAR2,
p_result OUT SYS_REFCURSOR
) AS
cursor_name INTEGER := DBMS_SQL.OPEN_CURSOR;
ROWS_PROCESSED INTEGER ;
v_string VARCHAR2(1000);
BEGIN
v_string:=' SELECT *
FROM CONTRACT C
WHERE 1 = 1 ';
IF(P_CONTRACT IS NOT NULL) THEN
v_string := v_string || ' AND C.CONTRACT_NAME = :P_CONTRACT ';
END IF;
v_string: = v_string || ' AND ROWNUM <= 10';
DBMS_SQL.PARSE(CURSOR_NAME,v_string,DBMS_SQL.NATIVE);
IF (P_CONTRACT IS NOT NULL) THEN
DBMS_SQL.BIND_VARIABLE(CURSOR_NAME, ':P_CONTRACT', P_CONTRACT);
END IF;
ROWS_PROCESSED := DBMS_SQL.EXECUTE(cursor_name);
p_result := DBMS_SQL.TO_REFCURSOR(cursor_name);
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(cursor_name) THEN
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END IF;
END ;
And I execute store like this:
set serveroutput on;
VARIABLE p_result REFCURSOR ;
Exec TEST('HNLT00014',:p_result);
print p_result;
I've always got this error :
Error starting at line : 10 in command -
BEGIN TEST('HNLT00014',:p_result); END;
Error report -
ORA-29471: DBMS_SQL access denied
ORA-06512: at "SYS.DBMS_SQL", line 1098
ORA-06512: at "TEST", line 6
ORA-06512: at line 1
29471. 00000 - "DBMS_SQL access denied"
*Cause: DBMS_SQL access was denied due to security concerns.
*Action: Check the alert log and trace file for more information.
I tried close and re-open newly established session like #Nick Krasnov recommended Link
But it didn't work. Someone can help me? I'm using Oracle 12C.
Thanks!

Related

how to write select statement inside if in PostgreSQL

I'm trying to write select statement inside if in PostgreSQL but getting error like ERROR: syntax error at or near "SELECT" please help me to solve this error
LINE 39: SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
BEGIN
if p_mobile_no=usersdefotp_mobile_no
then
P_OTP :='123456'
else
SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
P_OTP :=LPAD(W_OTPNUM::TEXT, 6, '0');
INSERT INTO usersdefotp(P_OTP)
end if
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_OTP := NULL;
END;
You can use declarations in a Procedure as an Array on PostgreSQL, like this one:
do $$
declare
randoms text[];
begin
-- store data
randoms = ARRAY(SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
P_OTP :=LPAD(W_OTPNUM::TEXT, 6, '0'));
if something
then
do something
else
return format("%s", randoms)
end if;
end
$$;
That way you can store your select and then use him when needed to return;

debugging psql - session procedure

I am trying to modify an existing sessions procedure to add cycle count.The error I am getting is
SQL Error [42601]: ERROR: syntax error at or near "END"
Position: 3587
--call transactions_packs.tep_session()
CREATE OR REPLACE PROCEDURE transactions_packs.tep_session()
LANGUAGE plpgsql
AS $procedure$
DECLARE
session "transactions_packs"."simple_sessions";
"session_toSearch" TEXT;
"end_timestamp" TIMESTAMP WITH TIME ZONE;
"energy" NUMERIC;
"charge" NUMERIC;
"duration" NUMERIC;
"cycle_count" numeric;
"f" record ;
BEGIN
cycle_count = '0';
-- go to statement fore session reset
FOR session IN SELECT * FROM "transactions_packs"."simple_sessions" WHERE "sessionDuration" IS NULL
LOOP
BEGIN
IF session."sessionType" = 0 THEN
"session_toSearch" := 'Charging';
ELSIF session."sessionType" = 1 THEN
"session_toSearch" := 'Discharging';
END IF;
-- Session_count:Start
EXECUTE FORMAT('
FOR f IN select (current' || '%s' || '), "timestamp"
FROM "transactions_packs"."basic_measurements_packs" a order by a."timestamp" desc
LOOP
BEGIN
IF AVG((current' || '%s' || '))
OVER (ORDER BY "f"."timestamp" ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) > 0.01
then cycle_count = cycle_count + 1;
END IF;
END
END LOOP;',"session_toSearch","session_toSearch")
-- get value from If and else statement to fetch records from charging and discharging col
--Session_count :End
END ;
END LOOP;
end;
$procedure$
;
where -
schema is transactions_packs
tables are -
simple_sessions
basic_measurements_packs
Please let me know if there is any part of query is which cannot be understood.
The variable "hell" sounds like useless here, try something like this :
create or replace procedure "public"."extract"(arg json)
language plpgsql as $$
begin
raise notice 'test:%', arg->'global'->>'packetType';
raise notice 'test1:%', arg-> 'transactional'->>'A';
-- freeze the input
end ;
$$;

How to display Notice successfull in postgres

I want to display in my CMD console, ONLY the success message if my request its OK:
Example :
BEGIN
INSERT / UPDATE .... //request
EXCEPTION
WHEN successful_completion THEN RAISE NOTICE 'INFO : MESSAGE RESQUEST IS OK ';
END;
THIS MY CODE EDIT:
DO $$
BEGIN
BEGIN
UPDATE user set age = 22 , date_inscription = '2018-01-30' where id = 154;
EXCEPTION
WHEN ??? THEN ????
END;
RAISE NOTICE 'INFO : L''age et date inscription ont été mis à jour'; // MESSAGE OK
END;
$$
There is no message successful_completion, but I guess you know that.
If you want to send a notice on error, put it into the exception handler.
If you want to send a notice on success, put the RAISE after the SQL statement in question.
If you want to send a notice no matter what, put the RAISE after the whole block.
An example for the second option:
BEGIN
INSERT ...
RAISE NOTICE 'INFO : MESSAGE REQUEST IS OK ';
EXCEPTION
WHEN OTHERS THEN
/* handle the error */
END;
If you want to prevent having the notice INFO : MESSAGE REQUEST IS OK in case of failure, you should but it just between the INSERT statement and the EXCEPTION block, as here:
CREATE OR REPLACE FUNCTION test_notice (int_id INTEGER) RETURNS integer AS
$do$
BEGIN
INSERT INTO tbl VALUES (int_id);
RAISE NOTICE 'INFO : MESSAGE REQUEST IS OK ';
RETURN 0;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Ignoring error';
RETURN 1;
END;
$do$ LANGUAGE plpgsql;
Here is the DDL for the tbl table:
DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl (id int);
ALTER TABLE tbl ADD CONSTRAINT tbl_pk PRIMARY KEY (id);
And here is a test case, with 1 success, 1 failure and then 1 success:
()=#SELECT test_notice (1);
NOTICE: INFO : MESSAGE REQUEST IS OK
test_notice
-------------
0
(1 row)
()=#SELECT test_notice (1);
NOTICE: Ignoring error
test_notice
-------------
1
(1 row)
()=#SELECT test_notice (2);
NOTICE: INFO : MESSAGE REQUEST IS OK
test_notice
-------------
0
(1 row)
There are 2 other methods available if you insist on actually checking, other than retrieving a row from the processed set. First both Insert and Update set FOUND True if a row was processed and False otherwise. The other is to get the actual number of rows processed via Get Diagnostics. The following block demonstrates both.
do $$
declare rows_processed integer;
begin
insert into users(id, age, date_inscription)
values (154, 20, now()::date)
, (164, 22, now()::date);
get diagnostics rows_processed = row_count;
raise notice '1. After Insert: Found=%, Num of Rows=%', found, rows_processed;
UPDATE users
set age = age+2 , date_inscription = now()::date
where id in (154, 160) ; -- one of two
get diagnostics rows_processed = row_count;
raise notice '2. After Update: Found=%, Num of Rows=%', found, rows_processed;
UPDATE users
set age = 12 ,
date_inscription = now()::date
where id = 205;
get diagnostics rows_processed = row_count;
raise notice '3. After Update (no such id): Found=%, Num of Rows=%', found, rows_processed;
delete from users;
get diagnostics rows_processed = row_count;
raise notice '4. After Delete: Found=%, Num of Rows=%', found, rows_processed;
end;
$$;

Function or loop using table and topologies names as arguments in Postgresql

I'm working with topologies in PostGIS and to create a TopoGeometry column, I'm using this loop:
DO $$DECLARE r record;
BEGIN
FOR r IN SELECT * FROM table_uf_11 LOOP
BEGIN
UPDATE table_uf_11 SET tg_geom = toTopoGeom(ST_Force2D(geom),'topology_uf_11', 1, 1)
WHERE gid= r.gid;
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Loading of record % failed: %', r.gid, SQLERRM;
END;
END LOOP;
END$$;
The reason for using this loop is because in some rows the toTopoGeom function displays error, but are just a few cases, for exemplo 38 cases in 24.000.
Using this structure I can identify which cases are problematic in the log and fix them later.
My problem is that I have another 26 tables with their respective topologies, all of them identified by the state code, for exemplo:
table_uf_12 / topology_uf_12
table_uf_13 / topology_uf_13
table_uf_14 / topology_uf_14
...
table_uf_53 / topology_uf_53
The state code are not necessarily sequential, but the names has the same pattern. Column names as geom and tg_geom are equal for all tables.
How can I make a function or another loop structure to replicate this process in all 27 tables and the same time save the log of each table?
I tried to make a function, but in this case the arguments would be the table name and the topology name, and i'm having difficult to elaborate this structure.
Any suggestions?
I think this should do it:
DO $BODY$
DECLARE
t regclass;
gid bigint;
BEGIN
FOR t IN SELECT oid::regclass FROM pg_class WHERE relname ~ '^table_uf_\d+$' LOOP
FOR gid IN EXECUTE 'SELECT gid FROM ' || t::text LOOP
BEGIN
EXECUTE
' UPDATE ' || t::text ||
' SET tg_geom = toTopoGeom(ST_Force2D(geom), $2, 1, 1)'
' WHERE gid = $1'
USING gid, replace(t::text, 'table', 'topology');
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Loading of record % failed: %', gid, SQLERRM;
END;
END LOOP;
END LOOP;
END
$BODY$

How to use "RAISE INFO, RAISE LOG, RAISE DEBUG” to track log in PostgreSQL function?

CREATE OR REPLACE FUNCTION mover(src text, dst text, cpquery text, conname text, ifbin boolean) returns void as
$$
DECLARE
cnt integer;
dlcnt integer;
del_count integer;
ret text;
BEGIN
SELECT pg_catalog.dblink_copy_open(conname, dst, ifbin) INTO ret ;
RAISE LOG 'dblink_open %',ret;
execute 'SELECT 1 as check FROM ' || src ||' limit 1' into cnt;
IF cnt=0 THEN
PERFORM pg_sleep(2);
END IF;
IF ifbin=true THEN
RAISE DEBUG 'Start to Copy data with binary';
execute 'COPY (' || cpquery || ' ) to function pg_catalog.dblink_copy_write with binary';
RAISE DEBUG 'Finish Copy data';
ELSE
RAISE DEBUG 'Start to Copy data without binary';
execute 'COPY (' || cpquery || ' ) to function pg_catalog.dblink_copy_write';
RAISE DEBUG 'Finish Copy data';
END IF;
execute 'DELETE FROM ' || src;
GET DIAGNOSTICS del_count=ROW_COUNT;
RAISE INFO 'DELETE % rows',del_count;
SELECT pg_catalog.dblink_copy_end() INTO ret;
RAISE LOG 'dblink_end %',ret;
END;
$$
language plpgsql;
As code, I want to put some message into log by using RAISE, but where is the location
of my log file ? and where RAISE DEBUG output?
They can either be output to the Postgres log, reported back to the client, or both. These are controlled by server-side settings, log_min_messages and client_min_messages.
See the following doc for more details:
http://www.postgresql.org/docs/current/static/plpgsql-errors-and-messages.html
http://www.postgresql.org/docs/current/static/runtime-config-logging.html
As #a_horse_with_no_name suggested: These parameters can also be set via the SET command from the client.
It can be set via the SQL: set client_min_messages to 'debug';