I'm trying to output my procedure, with a secret password. When i try to run my code it doesn't work.
CREATE OR replace Procedure hiddenPasswords(
p_MA_ID IN MitarbeiterAccounts.MitarbetierAccountID%TYPE,
p_M_Login IN MitarbeiterAccounts.Mitarbeiter_Login%TYPE,
p_M_Password IN MitarbeiterAccounts.Mitarbeiter_Password%TYPE)
IS
BEGIN
INSERT INTO MitarbeiterAccounts(MitarbeiterAccountsID,
MitarbeiterAccounts_Login, Mitarbeiter_Password)
VALUES(p_MA_ID, p_M_Login, HASHBYTES('SHA2_512', p_M_Password));
END;
/
EXEC hiddenPasswords p_MA_ID = 4, p_M_Login = 'Admin' p_M_Password = N'123';
I'm getting that HASHBYTES is invalid identifier
Well, Oracle doesn't have any built-in function called HASHBYTES. It is there in SQL SERVER but not in Oracle
instead you can use DBMS_CRYPTO.HASH if you have that privilege for the same.
DBMS_CRYPTO provides an interface to encrypt and decrypt stored data, and can be used in conjunction with PL/SQL programs running network communications
DBMS_CRYPTO
Update
For eg., I have used RAW here. You can check other Overloaded functions in the above link where you can use BLOB, CLOB as well.
DECLARE
l_pwd VARCHAR2(19) := 'mysecretpassword';
l_ccn_raw RAW(128) := utl_raw.cast_to_raw(l_pwd);
l_encrypted_raw RAW(2048);
BEGIN
dbms_output.put_line('CC: ' || l_ccn_raw);
l_encrypted_raw := dbms_crypto.hash(l_ccn_raw, 1);
dbms_output.put_line('MD4: ' || l_encrypted_raw);
l_encrypted_raw := dbms_crypto.hash(l_ccn_raw, 2);
dbms_output.put_line('MD5: ' || l_encrypted_raw);
l_encrypted_raw := dbms_crypto.hash(l_ccn_raw, 3);
dbms_output.put_line('SH1: ' || l_encrypted_raw);
END;
/
OUTPUT
CC: 6D7973656372657470617373776F7264
MD4: BBBA2CBC2F6E0F158D06B34F819DB5F6
MD5: 4CAB2A2DB6A3C31B01D804DEF28276E6
SH1: 08CD923367890009657EAB812753379BDB321EEB
Related
I am trying to create a button on a page in my application that will download the full table I am referencing as a CSV file. I cannot use interactive reports > actions > download CSV because the interactive reports have hidden columns. I need all columns to populate in the CSV file.
Is there a way to create a SQL Script and reference it in the button?
I have already tried the steps referenced in this link: Oracle APEX - Export a query into CSV using a button but it does not help as my queries will contain columns that are hidden in the Interactive Report.
Welcome to StackOverflow!
One flexible option would be to use an application process, to be defined in the shared components (process point = ajax callback).
Something like this:
declare
lClob clob;
lBlob blob;
lFilename varchar2(250) := 'filename.csv';
begin
lClob := UNISTR('\FEFF'); -- was necessary for us to be able to use the files in MS Excel
lClob := lClob || 'Tablespace Name;Table Name;Number of Rows' || utl_tcp.CRLF;
for c in (select tablespace_name, table_name, num_rows from user_tables where rownum <= 5)
loop
lClob := lClob || c.tablespace_name || ';' || c.table_name || ';' || c.num_rows || utl_tcp.CRLF;
end loop;
lBlob := fClobToBlob(lClob);
sys.htp.init;
sys.owa_util.mime_header('text/csv', false);
sys.htp.p('Conent-length: ' || dbms_lob.getlength(lBlob));
sys.htp.p('Content-Disposition: attachment; filename = "' || lFilename || '"');
sys.htp.p('Cache-Control: no-cache, no-store, must-revalidate');
sys.htp.p('Pragma: no-cache');
sys.htp.p('Expires: 0');
sys.owa_util.http_header_close;
sys.wpg_docload.download_file(lBlob);
end;
This is the function fClobToBlob:
create function fClobToBlob(aClob CLOB) RETURN BLOB IS
tgt_blob BLOB;
amount INTEGER := DBMS_LOB.lobmaxsize;
dest_offset INTEGER := 1;
src_offset INTEGER := 1;
blob_csid INTEGER := nls_charset_id('UTF8');
lang_context INTEGER := DBMS_LOB.default_lang_ctx;
warning INTEGER := 0;
begin
if aClob is null then
return null;
end if;
DBMS_LOB.CreateTemporary(tgt_blob, true);
DBMS_LOB.ConvertToBlob(tgt_blob, aClob, amount, dest_offset, src_offset, blob_csid, lang_context, warning);
return tgt_blob;
end fClobToBlob;
On the page, you need to set your button action to "Redirect to Page in this Application", the target Page to "0". Under "Advanced", set Request to "APPLICATION_PROCESS=downloadCSV", where downloadCSV is the name of your application process.
If you need to parameterize your process, you can do this by accessing page items or application items in your application process.
Generating the CSV data can be cumbersome, but there are several packages out there that make it easier. The alexandria packages are one of them:
https://github.com/mortenbra/alexandria-plsql-utils
An example on how to use the CSV Package is here:
https://github.com/mortenbra/alexandria-plsql-utils/blob/master/demos/csv_util_pkg_demo.sql
In my user table, the username column is encoded via PBEWithMD5AndDES algorithm. Now I want something like this:
WITH TEMP
AS (SELECT E.UAC_USER_ID AS ID,
E.UAC_USER_USERNAME AS USERNAME,
E.UAC_USER_FIRSTNAME || ' ' || E.UAC_USER_LASTNAME AS NAME,
E.UAC_USER_PERSONELCODE AS PERSONELCODE
FROM UAC_USERS E
WHERE E.UAC_USER_ISENABLED = 1)
SELECT *
FROM TEMP
WHERE 1 = 1 AND DECODE (USERNAME) = 'admin'
is there any embedded function in oracle that can decode the selected field?
I can only give you direction to solve problem, not answer.
Oracle has package dbms_crypto which may be can help you.
See examples https://docs.oracle.com/database/121/ARPLS/d_crypto.htm#ARPLS65690
You can find encryption_type
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES256
+ DBMS_CRYPTO.CHAIN_CBC -- description in doc
+ DBMS_CRYPTO.PAD_PKCS5; -- description in doc
In DBMS_CRYPTO there is another constant DBMS_CRYPTO.ENCRYPT_PBE_MD5DES.
Theoretically this may help:
encryption_type PLS_INTEGER := -- total encryption type
DBMS_CRYPTO.ENCRYPT_PBE_MD5DES
+ DBMS_CRYPTO.CHAIN_CBC -- description in doc
+ DBMS_CRYPTO.PAD_PKCS5; -- description in doc
But using this encryption_type in code I get error. I also try several combination and change code but finally i give up. May be one of the reason is the constant DBMS_CRYPTO.ENCRYPT_PBE_MD5DES doesn't described in doc or I should change smt else in example. .
I have below code. I am using Oracle 11g.
SELECT DBMS_OBFUSCATION_TOOLKIT.md5 (input => UTL_RAW.cast_to_raw(
FIRST_NAME
||LAST_NAME
)) md5_key ,
FIRST_NAME ,
LAST_NAME
FROM C_NAME_TAB
WHERE PKEY='1234'
How can i call this code? Can i directly execute this code in sqldeveloper?
In Oracle 12c you can use the function STANDARD_HASH. It does not require any additional privileges.
select standard_hash('foo', 'MD5') from dual;
The dbms_obfuscation_toolkit is deprecated (see Note here). You can use DBMS_CRYPTO directly:
select rawtohex(
DBMS_CRYPTO.Hash (
UTL_I18N.STRING_TO_RAW ('foo', 'AL32UTF8'),
2)
) from dual;
Output:
ACBD18DB4CC2F85CEDEF654FCCC4A4D8
Add a lower function call if needed. More on DBMS_CRYPTO.
I would do:
select DBMS_CRYPTO.HASH(rawtohex('foo') ,2) from dual;
output:
DBMS_CRYPTO.HASH(RAWTOHEX('FOO'),2)
--------------------------------------------------------------------------------
ACBD18DB4CC2F85CEDEF654FCCC4A4D8
#user755806 I do not believe that your question was answered. I took your code but used the 'foo' example string, added a lower function and also found the length of the hash returned. In sqlplus or Oracle's sql developer Java database client you can use this to call the md5sum of a value. The column formats clean up the presentation.
column hash_key format a34;
column hash_key_len format 999999;
select dbms_obfuscation_toolkit.md5(
input => UTL_RAW.cast_to_raw('foo')) as hash_key,
length(dbms_obfuscation_toolkit.md5(
input => UTL_RAW.cast_to_raw('foo'))) as hash_key_len
from dual;
The result set
HASH_KEY HASH_KEY_LEN
---------------------------------- ------------
acbd18db4cc2f85cedef654fccc4a4d8 32
is the same value that is returned from a Linux md5sum command.
echo -n foo | md5sum
acbd18db4cc2f85cedef654fccc4a4d8 -
Yes you can call or execute the sql statement directly in sqlplus or sql developer. I tested the sql statement in both clients against 11g.
You can use any C, C#, Java or other programming language that can send a statement to the database. It is the database on the other end of the call that needs to be able to understand the sql statement. In the case of 11 g, the code will work.
#tbone provides an excellent warning about the deprecation of the dbms_obfuscation_toolkit. However, that does not mean your code is unusable in 12c. It will work but you will want to eventually switch to dbms_crypto package. dbms_crypto is not available in my version of 11g.
To calculate MD5 hash of CLOB content field with my desired encoding without implicitly recoding content to AL32UTF8, I've used this code:
create or replace function clob2blob(AClob CLOB) return BLOB is
Result BLOB;
o1 integer;
o2 integer;
c integer;
w integer;
begin
o1 := 1;
o2 := 1;
c := 0;
w := 0;
DBMS_LOB.CreateTemporary(Result, true);
DBMS_LOB.ConvertToBlob(Result, AClob, length(AClob), o1, o2, 0, c, w);
return(Result);
end clob2blob;
/
update my_table t set t.hash = (rawtohex(DBMS_CRYPTO.Hash(clob2blob(t.content),2)));
I have to move around 50+ validation functions into Oracle. I'm looking for the approach that runs fastest, but also would like to get around a boolean issue if possible. The return object for them all needs to be the same so that the application can react off the result in a consistent fashion and alert the user or display whatever popups, messages we may need. I created a valObj for this, but not sure yet if that is the best approach. The return format can be changed because the front-end that reacts off of it is not developed yet. In the end it will contain many different validation functions, from integer, number, phone, email, IPv4, IPv6, etc... This is what I have so far...
/***
This is the validation object.
It stores 1 for valid, 0 for not valid and some helper text that can be relayed back to the user.
***/
create or replace type valObj as object (
result number(1),
resultText varchar(32000)
);
/***
Coming from ColdFusion this seems clean to me but the function
will end up being a couple thousand lines long.
***/
create or replace function isValid(v in varchar2, format in varchar2)
return valObj
is
test number;
begin
if format = 'number' then
begin
test := to_number(v);
return valObj(1,null);
exception when VALUE_ERROR then return valObj(0,'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...');
end;
elsif format = 'integer' then
null; --TO DO
elsif format = 'email' then
null; --TO DO
elsif format = 'IPv4' then
null; --TO DO
elsif format = 'IPv6' then
null; --TO DO
end if;
--dozens of others to follow....
end;
/
/* Example Usage in SQL */
select isValid('blah','number') from dual; -- returns: (0, Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...)
select isValid('blah','number').result from dual; -- returns: 0
select isValid('blah','number').resulttext from dual; -- returns: Valid formats are: 12345, 12345.67, -12345, etc...
select isValid(1234567890.123,'number') from dual; -- returns: 1,{null}
select isValid(1234567890.123,'number').result from dual; -- returns: 1
select isValid(1234567890.123,'number').resulttext from dual; -- returns: {null}
/* Example Usage in PL/SQL */
declare
temp valObj;
begin
temp := isValid('blah','number');
if (temp.result = 0) then
dbms_output.put_line(temp.resulttext);
else
dbms_output.put_line('Valid');
end if;
end;
/
My questions are:
When using it in PL/SQL I would love to be able to do boolean checks instead like this: if (temp.result) then but I can't figure out a way, cause that won't work in SQL. Should I just add a 3rd boolean attribute to the valObj or is there another way I don't know of?
These validation functions could end up being called within large loops. Knowing that, is this the most efficient way to accomplish these validations?
I'd appreciate any help. Thanks!
UPDATE: I forgot about MEMBER FUNCTIONS. Thanks #Brian McGinity for reminding me. So I'd like to go with this method since it keeps the type and its functions encapsulated together. Would there be any speed difference between this method and a stand-alone function? Would this be compiled and stored the same as a stand-alone function?
create or replace type isValid as object (
result number(1),
resulttext varchar2(32000),
constructor function isValid(v varchar, format varchar) return self as result );
/
create or replace type body isValid as
constructor function isValid(v varchar, format varchar) return self as result as
test number;
begin
if format = 'number' then
begin
test := to_number(v);
self.result := 1;
self.resulttext := null;
return;
exception when VALUE_ERROR then
self.result := 0;
self.resulttext := 'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...';
return;
end;
elsif format = 'phone' then
null; --TO DO
end if;
--and many others...
end;
end;
/
/* Example Usage in SQL */
select isValid('a','number') from dual;
/* Example Usage in PL/SQL */
declare
begin
if (isValid('a','number').result = 1) then
null;
end if;
end;
/
TEST RESULTS:
/* Test isValid (the object member function), this took 7 seconds to run */
declare
begin
for i in 1 .. 2000000 loop
if (isValid('blah','number').result = 1) then
null;
end if;
end loop;
end;
/* Test isValid2 (the stand-alone function), this took 16 seconds to run */
declare
begin
for i in 1 .. 2000000 loop
if (isValid2('blah','number').result = 1) then
null;
end if;
end loop;
end;
Both isValid and isValid2 do the same exact code, they just run this line test := to_number(v); then do the exception if it fails and return the result. Does this appear to be a valid test? The Object member function method is actually faster than a stand-alone function???
The stand-alone function can be much faster if you set it to DETERMINISTIC and if the data is highly repetitive. On my machine this setting decreased run time from 9 seconds to 0.1 seconds. For reasons I don't understand that setting does not improve performance of the object function.
create or replace function isValid2(v in varchar2, format in varchar2)
return valObj
deterministic --<< Hit the turbo button!
is
test number;
begin
if format = 'number' then
begin
test := to_number(v);
return valObj(1,null);
exception when VALUE_ERROR then return valObj(0,'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...');
end;
end if;
end;
/
May also want to consider utilizing pls_integer over number. Don't know if it will buy you much, but documents suggest some gain will be had.
http://docs.oracle.com/cd/B10500_01/appdev.920/a96624/03_types.htm states,
"You use the PLS_INTEGER datatype to store signed integers. Its magnitude range is -2*31 .. 2*31. PLS_INTEGER values require less storage than NUMBER values. Also, PLS_INTEGER operations use machine arithmetic, so they are faster than NUMBER and BINARY_INTEGER operations, which use library arithmetic. For efficiency, use PLS_INTEGER for all calculations that fall within its magnitude range."
I am getting an Syntax Error when processing the following lines of code. Especially on the AQ_Query.Open;
procedure THauptfenster.Button1Click(Sender: TObject);
var
option: TZahlerArray;
begin
option := werZahlte;
AQ_Query.Close;
AQ_Query.SQL.Clear;
AQ_Query.SQL.Add('USE wgwgwg;');
AQ_Query.SQL.Add('INSERT INTO abrechnung ');
AQ_Query.SQL.Add('(`datum`, `titel`, `betrag`, `waldemar`, `jonas`, `ali`, `ben`)');
AQ_Query.SQL.Add(' VALUES ');
AQ_Query.SQL.Add('(:datum, :essen, :betrag, :waldemar, :jonas, :ali, :ben);');
AQ_Query.Parameters.ParamByName('datum').Value := DateToStr(mcDatum.Date);
AQ_Query.Parameters.ParamByName('essen').Value := ledTitel.Text;
AQ_Query.Parameters.ParamByName('betrag').Value := ledPreis.Text;
AQ_Query.Parameters.ParamByName('waldemar').Value := option[0];
AQ_Query.Parameters.ParamByName('jonas').Value := option[1];
AQ_Query.Parameters.ParamByName('ali').Value := option[2];
AQ_Query.Parameters.ParamByName('ben').Value := option[3];
AQ_Query.Open;
end;
The error:
I am using MySQL Delphi 2010.
USE and INSERT are two different SQL
commands.
MySQL does not support so
called "Batches".
=> you have to call these commands one-by-one
Looks to me like you're using backticks on the third AQ_Query.SQL.Add line, when you need to use normal single quotes.
Use the database in the sql script.
AQ_Query.SQL.Add('INSERT INTO wgwgwg.dbo.abrechnung ');
AQ_Query.SQL.Add('(`wgwgwg.dbo.abrechnung.datum`, `wgwgwg.dbo.abrechnungtitel`, `wgwgwg.dbo.abrechnungbetrag`, `wgwgwg.dbo.abrechnungwaldemar`, `wgwgwg.dbo.abrechnungjonas`, `wgwgwg.dbo.abrechnungali`, `wgwgwg.dbo.abrechnungben`)');
AQ_Query.SQL.Add(' VALUES ');
AQ_Query.SQL.Add('(:datum, :essen, :betrag, :waldemar, :jonas, :ali, :ben);');
AQ_Query.Parameters.ParamByName('datum').Value := DateToStr(mcDatum.Date);
AQ_Query.Parameters.ParamByName('essen').Value := ledTitel.Text;
AQ_Query.Parameters.ParamByName('betrag').Value := ledPreis.Text;
AQ_Query.Parameters.ParamByName('waldemar').Value := option[0];
AQ_Query.Parameters.ParamByName('jonas').Value := option[1];
AQ_Query.Parameters.ParamByName('ali').Value := option[2];
AQ_Query.Parameters.ParamByName('ben').Value := option[3];
You can also make a new connection to wgwgwg and refer your AQ_Query to the new connection