How do you convert SYS_GUID() to varchar? - oracle

In oracle 10g, how do you convert SYS_GUID() to varchar? I am trying something like:
select USER_GUID from user where email = 'user#example.com'
Which returns the RAW byte[]. Is it possible to use a function to convert the RAW to VARCHAR2 in the SQL statement?

Don't forget to use HEXTORAW(varchar2) when comparing this value to the RAW columns.
There is no implicit convesion from VARCHAR2 to RAW. That means that this clause:
WHERE raw_column = :varchar_value
will be impicitly converted into:
WHERE RAWTOHEX(raw_column) = :varchar_value
, thus making indices on raw_column unusable.
Use:
WHERE raw_column = HEXTORAW(:varchar_value)
instead.

Use RAWTOHEX(USER_GUID).

select RAWTOHEX(USER_GUID) from user where email = 'user#example.com'

Please don't mod-1 if I'm wrong. I'm going from memory so this a disclaimer to verify.
TO_CHAR is actually different between SQL and PL/SQL.
In SQL TO_CHAR does not take a raw as you have found out.
In PL/SQL To_CHAR will take a raw value.
So if you're in a procedure anyways, sometimes it easier to use a variable, but if you're just using SQL, go with the other answers here.

select CAST (USER_GUID AS VARCHAR2(100)) from user where email = 'user#example.com'

Related

Check queries output type

I'm working with Oracle DB and faced with a problem. I cannot say for sure what the type will value have once the output is generated.
I have the following simple query:
select 1+'1234' from dual;
For me it's clear that the output "1235" will present a simple number. But how can I check that it is not converted into text afterwards for example? Is there any kind of "type_of" function which will help me with that?
Thank you in advance for your help!
You can use the dump() function:
select dump(1+'1234') from dual;
which will give you the datatype, as well as the byte values used to represent tha value, which you don’t seem to be interested in here.
Typ=2 Len=3: 194,13,36
where type 2 is NUMBER.
I think a way to find the return type would be to create a table using that query.
for eg.
create table temp_table_name1 as select 1+'1234' a from dual;
desc temp_table_name1;
Should give the type.
If you are worried about the return type then you can manually set it using
select Cast(1+'1234' As Varchar2(30)) a from dual;
OR
select Cast(1+'1234' As Number(4)) a from dual;

Oracle CHAR Comparison Not Working in Function

Could someone please explain to me the difference between the below two Oracle queries? I know they look very similar but the first one returns results and the second one does not. My implementation of the function can be seen below as well.
--Returns results
SELECT *
FROM <TABLE_NAME>
WHERE ID = CAST(<UserID> AS CHAR(2000)); --ID is defined as CHAR(8) in the DB.
--Does not return results
SELECT *
FROM <TABLE_NAME>
WHERE ID = CAST_TO_CHAR(<UserID>); --ID is defined as CHAR(8) in the DB.
--Function definition
CREATE OR REPLACE FUNCTION CAST_TO_CHAR(varToPad IN VARCHAR2)
RETURN CHAR IS returnVal CHAR(2000);
BEGIN
SELECT CAST(varToPad AS CHAR(2000))
INTO returnVal
FROM DUAL;
RETURN returnVal;
END;
/
It almost seems to me that the type is not persisting when the value is retrieved from the database. From what I understand from CHAR comparisons in Oracle, it will take the smaller of the two fields and truncate the larger one so that the sizes match (that is why I am casting the second variable to length 2000).
The reason that I need to achieve something like this is because a vendor tool that we are upgrading from DB2 to Oracle defined all of the columns in the Oracle database as CHAR instead of VARCHAR2. They did this to make their legacy code more easily portable to a distributed environment. This is causing big issues in our web applications because compares are now being done against fixed length CHAR fields.
I thought about using TRIM() but these queries will be accessed a lot and I do not want them to do a full table scan each time. I also considered RPAD(, ) but I don't really want to hard code lengths in the application as these may change in the future.
Does anyone have any thoughts about this? Thank you in advance for your help!
I have similar problem. It turned out that these are the rules of implicit data conversion. Oracle Database automatically converts a value from one datatype to another when such a conversion makes sense.
If you change your select:
SELECT *
FROM <TABLE_NAME>
WHERE CAST(ID as CHAR(2000)) = CAST_TO_CHAR(<UserID>);
You will see that's works properly.
And here's another test script showing that the function works correctly:
SET SERVEROUTPUT ON --for DBMS_OUTPUT.PUT_LINE.
DECLARE
test_string_c CHAR(8);
test_string_v VARCHAR2(8);
BEGIN
--Assign the same value to each string.
test_string_c := 'string';
test_string_v := 'string';
--Test the strings for equality.
IF test_string_c = CAST_TO_CHAR(test_string_v) THEN
DBMS_OUTPUT.PUT_LINE('The names are the same');
ELSE
DBMS_OUTPUT.PUT_LINE('The names are NOT the same');
END IF;
END;
/
anonymous block completed
The names are the same
Here are some rules govern the direction in which Oracle Database makes implicit datatype conversions:
During INSERT and UPDATE operations, Oracle converts the value to
the datatype of the affected column.
During SELECT FROM operations, Oracle converts the data from the
column to the type of the target variable.
When comparing a character value with a numeric value, Oracle
converts the character data to a numeric value.
When comparing a character value with a DATE value, Oracle converts
the character data to DATE.
When making assignments, Oracle converts the value on the right side
of the equal sign (=) to the datatype of the target of the assignment
on the left side.
When you use a SQL function or operator with an argument of a
datatype other than the one it accepts, Oracle converts the argument
to the accepted datatype.
Complete list of datatype comparison rules you can explore here

Good way to deal with comma separated values in oracle

I am getting passed comma separated values to a stored procedure in oracle. I want to treat these values as a table so that I can use them in a query like:
select * from tabl_a where column_b in (<csv values passed in>)
What is the best way to do this in 11g?
Right now we are looping through these one by one and inserting them into a gtt which I think is inefficient.
Any pointers?
This solves exactly same problem
Ask Tom
Oracle does not come with a built-in tokenizer. But it is possible to roll our own, using SQL Types and PL/SQL. I have posted a sample solution in this other SO thread.
That would enable a solution like this:
select * from tabl_a
where column_b in ( select *
from table (str_to_number_tokens (<csv values passed in>)))
/
In 11g you can use the "occurrence" parameter of REGEXP_SUBSTR to select the values directly in SQL:
select regexp_substr(<csv values passed in>,'[^,]+',1,level) val
from dual
connect by level < regexp_count(<csv values passed in>,',')+2;
But since regexp_substr is somewhat expensive I am not sure if it is the most effective in terms of being the fastest.

using ansi sql syntax for formatting Numeric

I am using two different databases for my project,
Oracle and Apache Derby, and am trying as much as possible to use the ANSI SQL syntax supported by both of the databases.
I have a table with a column amount_paid NUMERIC(26,2).
My old code, which was using Oracle db, needed to retrieve value in this format
SELECT LTRIM(TO_CHAR(amount_paid,'9,999,999,999,999.99'))
How can I convert a numeric value to such a string in the format '9,999,999,999,999.99' using ANSI sql syntax?
I think this is the wrong approach. The format mask is for display purposes, so it really ought to be the concern of the presentation layer. All your data access layer should do is merely execute:
select amount_paid
from your_table
where ....
This syntax will obviously work whatever database your app attaches to.
Then put the formatting code in the front-end, where it belongs.
My knowledge is not encylopedic but as far as I know there isn't an ANSI function to do what you want (although I'd be glad to find out I'm wrong :-). CONVERT converts between character sets but does not, as best I can see, do the formatting work you want. CAST converts values between data types but, again, doesn't do formatting.
If Derby doesn't support the Oracle-style TO_CHAR function you may have to roll your own function, let's call it MY_TO_CHAR. In Oracle the implementation might be
FUNCTION MY_TO_CHAR(nValue IN NUMBER,
strOracle_format IN VARCHAR2,
strDerby_format IN VARCHAR2)
RETURN VARCHAR2
IS BEGIN
RETURN TO_CHAR(nValue, strOracle_format);
END MY_TO_CHAR;
In Derby you'd want to define this function in a similar manner, taking the appropriate value and format and invoking Derby's equivalent of TO_CHAR with the Derby formatting string.
EDIT: I agree with #APC - a lot of these issues disappear if you don't require the backend to do what is basically front-end work.
Share and enjoy.

Oracle last_ddl_time format

I have to query all_objects table where last_ddl_time='01 jan 2010' but it refuses the date format...
Any body give me the exact format to query?
As AKF said, you should be using Trunc unless you know the exact time the DDL was modified. Your query you added in the comments is looking for any objects where the DDL changed at 1/1/2010 00:00:00. Try:
SELECT *
FROM all_objects
WHERE trunc(last_ddl_time) = to_date('01-01-2010','dd-mm-yyyy');
I suggest you to use de date literal:
where trunc(last_ddl_time) = date '2010-01-01'
You can use the to_date function to format your date. If you enter a literal string, Oracle will attempt to convert that string using to_date with a default format 'DD-MON-YY', so your date would look like "01-JAN-10". As Oracle will be using this same function, you might want to put it in yourself and enjoy the finer granularity that custom formatting can provide.
It would be good to note that the dates stored in that column most likely have more precise dates, including hours and minutes, etc. Though you will be taking a bit of a performance hit, you might be better served using trunc(last_ddl_time) if you are testing with =.
There is some good info on Dates in Oracle at this link.
SELECT *
FROM all_objects t
WHERE trunc(t.last_ddl_time, 'DD') = to_date('2010-JAN-01', 'YYYY-MON-DD');

Resources