Access Oracle Apex Application Settings from PL/SQL - oracle

I've created an apex application setting FOO with value bar following these instructions.
When I try to access the setting from the SQL Workshop > SQL Commands page I see
Requested Application Setting #FOO# is not defined. Here is the SQL command I am running to retrieve the value:
declare
l_value varchar2(4000);
begin
l_value := APEX_APP_SETTING.GET_VALUE( p_name => 'FOO');
dbms_output.put_line(l_value);
end;
Any idea why this won't work?

Since you are not executing the code from within an APEX session, you need create an APEX session or attach yourself to to an existing APEX session otherwise there is no way to know what workspace/application to get the setting from. If the code was running from within a page, then your existing code would work.
Try executing the code below, but modify your APP ID and PAGE ID to an actual app/page within your APEX application. The username does not matter.
DECLARE
l_value VARCHAR2 (4000);
BEGIN
apex_session.create_session (p_app_id => 100, p_page_id => 2, p_username => 'any_username');
l_value := APEX_APP_SETTING.GET_VALUE (p_name => 'FOO');
DBMS_OUTPUT.put_line (l_value);
apex_session.delete_session;
END;
If you want to try building a function to return the setting value, I would recommend building a function like this
CREATE OR REPLACE FUNCTION FN_APP_CONFIG (
p_setting_name APEX_190200.WWV_FLOW_APP_SETTINGS.NAME%TYPE,
p_app_id APEX_190200.WWV_FLOW_APP_SETTINGS.FLOW_ID%TYPE DEFAULT APEX_APPLICATION.g_flow_id)
RETURN APEX_190200.WWV_FLOW_APP_SETTINGS.VALUE%TYPE
IS
l_value APEX_190200.WWV_FLOW_APP_SETTINGS.VALUE%TYPE;
BEGIN
SELECT VALUE
INTO l_value
FROM APEX_190200.WWV_FLOW_APP_SETTINGS
WHERE flow_id = p_app_id AND name = p_setting_name;
RETURN l_value;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN NULL;
WHEN TOO_MANY_ROWS
THEN
RETURN NULL;
END;
/

Related

Oracle Context equivalent for DB2

I am currently migrating from oracle to DB2. I have actively used sys_context in most of the applications to get the userID of logged in user through sessions(IIS and .net framework).
I am looking to convert the following set of scripts from oracle to DB2. So far not able to find any equivalent for oracle context in DB2.
SQL> create context my_ctx
2 using pkg_ctx;
Context created.
SQL> create package pkg_ctx
2 as
3 procedure set_context;
4 end;
5 /
Package created.
SQL> create or replace package body pkg_ctx
2 as
3 procedure set_context
4 as
5 begin
6 dbms_session.set_context( 'MY_CTX', 'USERNAME', 'test' );
7 end;
8 end;
9 /
Package body created.
SQL> exec pkg_ctx.set_context;
PL/SQL procedure successfully completed.
SQL> select sys_context( 'MY_CTX', 'USERNAME' )
2 from dual;
SYS_CONTEXT('MY_CTX','USERNAME')
-------------------------------------------------------------------------------
test
Assuming you work with Db2 for LUW, you can use one of the CURRENT CLIENT_* registry variables to pass session context information from the client application to the server. For example, during the session initialization on the client side you would issue SET CURRENT CLIENT_USERID='stacky', then on the server that variable can be read by a routine or a trigger.
It worked like this, haven't tried it at application level. But from the database tried to register 2 users from 2 different instances of the same database on DB2.
call sysproc.wlm_set_client_info('stacky',null,null,null,null);
select wlm_set_client_info from sysibm.sysdummy1;
returns stacky
from another instance of the same database
call sysproc.wlm_set_client_info('test',null,null,null,null);
select wlm_set_client_info from sysibm.sysdummy1;
returns test.
Will try this from the application level through creating sessions of the users, will monitor how exactly this works with the special registers.
Not sure if this is the exact way to do this, will explore more and keep updated.
For replicating a similar situation in our environment, while doing the migration from oracle to DB2 LUW.
The below procedure sets up the all the context values in user_id (limited to varchar 255) field which we need as as 'key1:value1|key2:value2|'
Procedure to setup the context values
CREATE OR REPLACE PROCEDURE setup_context(pValues IN VARCHAR)
IS
lValues VARCHAR2(255) := pValues;
BEGIN
--save the as is
wlm_set_client_info(lValues, NULL, NULL, NULL, NULL);
END;
Procedure to set the value of the desired key
CREATE OR REPLACE FUNCTION sys_context(prefix IN VARCHAR) RETURN VARCHAR IS
lValues VARCHAR2(255);
lParam VARCHAR2(255);
lKey VARCHAR2(255);
lValue VARCHAR2(255);
lIndex PLS_INTEGER;
BEGIN
--get the data from the current session
SELECT CURRENT CLIENT_USERID INTO lValues FROM dual;
LOOP
EXIT WHEN lValues IS NULL OR LENGTH(lValues) = 0;
lIndex := instr(lValues, '|');
IF lIndex > 0 THEN
lParam := substr(lValues, 1, lIndex-1);
lValues := substr(lValues, lIndex+1);
ELSE
lParam := lValues;
lValues := NULL;
END IF;
lIndex := instr(lParam, ':');
lKey := substr(lParam, 1, lIndex-1);
lValue := substr(lParam, lIndex+1);
--get the matching value
IF(lKey = prefix ) Then
RETURN lValue;
END IF;
END LOOP;
RETURN '';
END;
reference : https://www.ibm.com/support/knowledgecenter/en/SSEPEK_11.0.0/sqlref/src/tpc/db2z_sp_wlmsetclientinfo.html

Calling a function from Oracle forms

I am using Oracle Forms 6i with Oracle db 10g on a Windows machine, in a form, when i click on a button, the trigger WHEN-BUTTON-PRESSED is launched calling a function of a package in the database, Here is the PL/SQL code for both the trigger and the function:
The function:
Function test_function (code Varchar2) RETURN Varchar2 IS
BEGIN
if code IN ('Y') then
return('Yes');
else
return('no');
endif;
END;
The trigger:
DECLARE
message_test varchar2(20);
BEGIN
message_test := pkg_test.test_function('Y');
message('the message is: ' || message_test);pause;
END;
My problem here is that it doesn't show anything, but when i write pkg_test.test_function('Y') in sql*plus or in SqlDevelopper it shows 'Yes' as a result,
Or when i change message_test := pkg_test.test_function('Y'); with select pkg_test.test_function('Y') into message_test from test; it works also.
what might be the cause of that?
PS: this is just a test code, the actual code is more complex than that.
If it is just test, Can you try show alert () function ?
DECLARE
message_test varchar2(20);
alert_resp number;
BEGIN
message_test := pkg_test.test_function('Y');
set_alert_property('ALERT_OK','the message is: ' || message_test);
alert_resp := show_alert('ALERT_OK');
END;
Make sure that you create alert ALERT_OK in your forms alerts.

Oracle data masking

We have one requirement to mask a particular table column using a Oracle function which gives persistent masked output string.
We tried Oracle Hash Function but it does not give String type return value.
We tried Oracle Random function (dbms_random.string) but it does not give Persistent output string.
I read on internet that this is called deterministic masking. But we do not want to use Oracle Enterprise Manager; however we require a direct Oracle function.
Please suggest.
This problem is easily solved in 12c with the function STANDARD_HASH.
The solution in previous versions is only slightly more complicated. Build a simple wrapper around DBMS_CRYPTO that acts just like STANDARD_HASH:
--Imitation of the 12c function with the same name.
--Remember to drop this function when you upgrade!
create or replace function standard_hash(
p_string varchar2,
p_method varchar2 default 'SHA1'
) return varchar2 is
v_method number;
v_invalid_identifier exception;
pragma exception_init(v_invalid_identifier, -904);
begin
--Intentionally case-sensitive, just like the 12c version.
if p_method = 'SHA1' then
v_method := dbms_crypto.hash_sh1;
--These algorithms are only available in 12c and above.
$IF NOT DBMS_DB_VERSION.VER_LE_11 $THEN
elsif p_method = 'SHA256' then
v_method := dbms_crypto.hash_sh256;
elsif p_method = 'SHA384' then
v_method := dbms_crypto.hash_sh384;
elsif p_method = 'SHA512' then
v_method := dbms_crypto.hash_sh512;
$END
elsif p_method = 'MD5' then
v_method := dbms_crypto.hash_md5;
else
raise v_invalid_identifier;
end if;
return rawToHex(dbms_crypto.hash(utl_raw.cast_to_raw(p_string), v_method));
end;
/
You may need to logon with SYS and grant your user access to DBMS_CRYPTO to make the function work:
grant execute on sys.dbms_crypto to <your_schema>;
Create a public synonym, grant it to everyone, and it works exactly the same way.
create public synonym standard_hash for <schema with function>.standard_hash;
grant execute on standard_hash to public;
select standard_hash('Some text', 'MD5') from dual;
9DB5682A4D778CA2CB79580BDB67083F
select standard_hash('Some text', 'md5') from dual;
ORA-00904: : invalid identifier
Here is a simple example of using the function:
update some_table
set column1 = standard_hash(column1),
column2 = standard_hash(column2);
But updating large amounts of data can be slow. It may be faster to create a new table, drop the old one, rename the new one, etc. And the hash value may be larger than the column size, it may be necessary to alter table some_table modify column1 varchar2(40 byte);
It amazes me how many products and tools there are to do such a simple thing.
If you looking something like mask the production data to move it into non-prod for integration testing. Below the "user defined" function would be helpful to you. This function will work only 10G and above.
create or replace function scrubbing(word in varchar2)
return varchar2
as
each_var char(2);
final_val varchar2(100);
complete_data varchar2(4000);
each_word varchar2(1000);
cursor val is select substr(replace(word,' ','#'),-level,1) from dual connect by level<=length(word);
begin
open val;
--final_val:= '';
loop
fetch val into each_var;
exit when val%NOTFOUND;
--dbms_output.put_line(each_var);
final_val := trim(final_val)||trim(each_var);
--dbms_output.put_line(final_val);
select regexp_substr(final_val,'[A-Za-z]+') into each_word from dual;
select replace(translate(final_val,each_word,dbms_random.string('L',length(word))),'#',' ') into complete_data from dual;
end loop;
return complete_data;
end;
In Oracle 12C dbms_redact.add_policy is available. It can be used to get the masked value in the select query itself.
You can use dbms_crpyto package of oracle , first you need to convert varchar2 type to raw then mask the data according to the hash value.

How to describe a reference cursor associated with dynamic SQL in Oracle?

This is my first (edited) stackoverflow question, so please bear with me.
In Oracle 11g, I have a need to describe/interrogate the underlying columns of a reference cursor returned from a procedure call on another database over a dblink, in which the actual SQL is not always "explicit", but sometimes dynamically generated.
For example:
declare
v_ref_cur sys_refcursor;
v_cur_num number;
v_col_count number;
v_col_table dbms_sql.desc_tab3;
begin
myProc#myDblink(v_ref_cur, 'myvalue');
v_cur_num := dbms_sql.to_cursor_number(v_ref_cur);
dbms_sql.describe_columns3(v_cur_num, v_col_count, v_col_table);
...
end
If myProc() on the other database has an "explicit" SQL statement like:
open cursor for select * from foo where bar = myParam;
The cursor conversion and description (still) work just fine - I can determine the column names, types, lengths, etc returned by the procedure.
BUT, if myProc() on the other database involves dynamic SQL, like:
v_sql := 'select * from foo where bar = ''' || myParam || '''';
open cursor for v_sql;
I get an ORA-01001 invalid cursor error when attempting to call dbms_sql.to_cursor_number().
Is there a way to convert/describe a reference cursor derived from dynamic SQL as called from a remote procedure? If so, how? If not, why not?
Thanks for any/all assistance!
Using DBMS_SQL across a database link raises many different errors, at least some of which are Oracle bugs. Those problems can be avoided by putting all of the logic in a function compiled on the remote server. Then call that function remotely.
--Create and test a database link
create database link myself connect to <schema> identified by "<password>"
using '<connect string or service name>';
select * from dual#myself;
--myProc
create procedure myProc(p_cursor in out sys_refcursor, p_value varchar2) is
begin
--open p_cursor for select * from dual where dummy = p_value;
open p_cursor for 'select * from dual where dummy = '''||p_value||'''';
end;
/
--Simple function that counts and displays the columns. Expected value is 1.
create or replace function count_columns return number is
v_ref_cur sys_refcursor;
v_cur_num number;
v_col_count number;
v_col_table dbms_sql.desc_tab3;
begin
--ORA-01001: invalid cursor
--myProc#myself(v_ref_cur, 'myvalue');
myProc(v_ref_cur, 'myvalue');
--ORA-03113: end-of-file on communication channel
--v_cur_num := dbms_sql.to_cursor_number#myself(v_ref_cur);
v_cur_num := dbms_sql.to_cursor_number(v_ref_cur);
--Compilation error: PLS-00306:
-- wrong number or types of arguments in call to 'DESCRIBE_COLUMNS3'
--dbms_sql.describe_columns3#myself(v_cur_num, v_col_count, v_col_table);
dbms_sql.describe_columns3(v_cur_num, v_col_count, v_col_table);
return v_col_count;
end;
/
begin
dbms_output.put_line('Number of columns: '||count_columns#myself());
end;
/
Number of columns: 1

Oracle SQL Developer: how to view results from a ref cursor?

If I have a function which returns a reference cursor for a query, how can I view the result set of this in SQL Developer? Toad has a special tab for viewing the results of a reference cursor, this is the functionality I would like to find.
SET SERVEROUTPUT ON;
VARIABLE X REFCURSOR;
EXEC PROCEDURE_WITH_OUTPUT_SYS_REFCURSOR(:X);
PRINT X;
Double click the cursor fields in your result record. On the right side there is a "..." icon. Click this and you'll see the contents
Hi I know this was asked a while ago but I've just figured this out and it might help someone else. Not sure if this is exactly what you're looking for but this is how I call a stored proc and view the output in SQL Developer.
In SQL Developer when viewing the proc, right click and choose 'Run' or select Ctrl+F11 to bring up the Run PL/SQL window. This creates a template with the input and output params which you need to modify. To return the results of a sys_refcursor you then need to declare a row type that is exactly equivalent to the select stmt / sys_refcursor being returned by the proc. Below I declare "type t_row" which matches my output fields, then loop through the returned sys_refcursor. If t_row matches my sys_refcursor then it gets populated with each row of the sys_refcursor:
DECLARE
P_CAE_SEC_ID_N NUMBER;
P_FM_SEC_CODE_C VARCHAR2(200);
P_PAGE_INDEX NUMBER;
P_PAGE_SIZE NUMBER;
v_Return sys_refcursor;
type t_row is record (CAE_SEC_ID NUMBER,FM_SEC_CODE VARCHAR2(7),rownum number, v_total_count number);
v_rec t_row;
BEGIN
P_CAE_SEC_ID_N := NULL;
P_FM_SEC_CODE_C := NULL;
P_PAGE_INDEX := 0;
P_PAGE_SIZE := 25;
CAE_FOF_SECURITY_PKG.GET_LIST_FOF_SECURITY(
P_CAE_SEC_ID_N => P_CAE_SEC_ID_N,
P_FM_SEC_CODE_C => P_FM_SEC_CODE_C,
P_PAGE_INDEX => P_PAGE_INDEX,
P_PAGE_SIZE => P_PAGE_SIZE,
P_FOF_SEC_REFCUR => v_Return
);
-- Modify the code to output the variable
-- DBMS_OUTPUT.PUT_LINE('P_FOF_SEC_REFCUR = ');
loop
fetch v_Return into v_rec;
exit when v_Return%notfound;
DBMS_OUTPUT.PUT_LINE('sec_id = ' || v_rec.CAE_SEC_ID || 'sec code = ' ||v_rec.FM_SEC_CODE);
end loop;
END;
there are no way to display a refcursor in datagrid in sqldeveloper.
we can define a refcursor,call SP,then print refcursor,then data will be printed in Script output window in a plane text mode,but not in Query Result window.

Resources