I'm trying to check in which characterset DBMS_METADATA.GET_DDL() is returning the result. I tried to check it like that.
SELECT DUMP(
CAST(
DBMS_METADATA.GET_DDL('FUNCTION', 'MyFUNCTION', 'SCHEME')
AS VARCHAR2(4000)
),
16
)
FROM dual
However it doesn't show me characterset. I'm only getting result like this:
Typ=1 Len=1739: a,2...
My NLS_CHARACTERSET returns WE8MSWIN1252. Does GET_DDL() returns also in this characterset?
Change the second dump argument from 16 to 1016:
SELECT dump (CAST(DBMS_METADATA.GET_DDL('FUNCTION', 'MyFUNCTION', 'SCHEME') AS VARCHAR2(4000)), 16) FROM DUAL
Typ=1 Len=126 CharacterSet=AL32UTF8: a ...
db<>fiddle
This is explained in the documentation:
By default, the return value contains no character set information. To retrieve the character set name of expr, add 1000 to any of the preceding format values.
You also asked:
My NLS_CHARACTERSET returns WE8MSWIN1252. Does GET_DDL returns also in this characterset?
You are casting the result of the GET_DDL call to varchar2, so dump will tell you the character set of that cast value, which will be in your NLS_CHARACTERSET. The value actually returned by GET_DDL is a CLOB, which will also be in your NLS_CHARACTERSET.
Related
I have a oracle view in which we have column called dayofset which defined from subtraction of two date columns like(to_date(date_column1)-to_date(date_column2)) and it is stored as number(38) datatype.
2.so,when I run session in informatica to get data from oracle view to redshift.im getting error like "not a valid month".
3.Input values for that column is like (25-JAN-21,10-APR-13)
4.im getting the output values like 1,2,3,4... Like this all are integer values.(this column just do the datediff operation) and provide the difference between two dates.
Could you guys please help on this.
I have a oracle view in which we have column called dayofset which defined from subtraction of two date columns like to_date(date_column1)-to_date(date_column2) and it is stored as number(38) datatype.
Never use TO_DATE on a column that is already a DATE data type. Just use.
CREATE VIEW your_view (dayofset)
SELECT date_column1 - date_column2
FROM your_table;
If you use TO_DATE then it takes a string as the first argument so you are effectively performing an implicit conversion to a string to convert it back to a date and your code is the equivalent of:
CREATE VIEW your_view (dayofset)
SELECT TO_DATE(
TO_CHAR(
date_column1,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
),
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
-
TO_DATE(
TO_CHAR(
date_column2,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
),
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
FROM your_table;
Depending on your NLS_DATE_FORMAT session parameter, this could just be a waste of time or it could truncate the date and give you an unexpected result; however, any user can change their session parameters at any time so you may get different results for different users so you should NEVER rely on implicit conversions.
If your columns are not a DATE data-type but are strings then use an explicit format model (and, if required, language) in the conversion:
CREATE VIEW your_view (dayofset)
SELECT TO_DATE(string_column1, 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
- TO_DATE(string_column2, 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
FROM your_table;
I am currently doing some research on Oracle functions, and one thing that stumped me a bit is how Oracle determines the return datatype of TO_NUMBER().
TO_NUMBER() takes in three parameters, two of which are optional. The first parameter is the input string, with the second being a format string, and third being a NLS locale string.
The output of TO_NUMBER() is a NUMBER datatype, and Oracle has a good number of NUMBER datatypes including FLOAT, DEC, INTEGER, INT, REAL, etc.
My question is -- how does TO_NUMBER() determine which specific numeric datatype to return? Is it determined by the first optional parameter, the format string?
As #mathguy has pointed out, TO_NUMBER always returns a NUMBER. You can check this out yourself with the DUMP function. It will return the datatype and the internal representation of the data, eg
SQL> select dump(to_number('1')) from dual;
DUMP(TO_NUMBER('1'
------------------
Typ=2 Len=2: 193,2
SQL> select dump(to_number('1.123')) from dual;
DUMP(TO_NUMBER('1.123'))
------------------------
Typ=2 Len=4: 193,2,13,31
Even a float when passed to TO_NUMBER will become a NUMBER
SQL> select dump(to_number(1.0e+3f)) from dual;
DUMP(TO_NUMBER(1.0E
-------------------
Typ=2 Len=2: 194,11
My Question is:
create function jbmdate (p_date in varchar2)
return varchar2
as
begin
return to_char(to_date(p_date,'YYYYMMDD'),'DD.MM.YYYY');
end;
As you see this returns a varchar with default value : 4000 byte/char.
But the Problem is that it will be used within a GUI so 4000 is quit unlucky big.
So how could i possible change the return value of this varchar2 to (10 char)?
It should look like this
but i looks like this when used in the gui.
So the real problem is not the gui itself but the sql ... shown here in squirrle sql:
So how can i alter the Precision which is returned by the function.
SQL Fiddle
Oracle 11g R2 Schema Setup:
create function jbmdate (p_date in varchar2)
return varchar2
as
begin
return to_char(to_date(p_date,'YYYYMMDD'),'DD.MM.YYYY');
end;
/
Query 1:
SELECT '20180818' AS input,
jbmdate( '20180818' ) AS dt,
DUMP( jbmdate( '20180818' ) ) AS "dump"
FROM DUAL
Results:
| INPUT | DT | dump |
|----------|------------|---------------------------------------------|
| 20180818 | 18.08.2018 | Typ=1 Len=10: 49,56,46,48,56,46,50,48,49,56 |
As you can see from the output of the DUMP() function, the returned VARCHAR2 data type has a length of 10. Wherever your 3990 extra bytes are coming from it is not being generated by SQL or PL/SQL and you should look further downstream in the application that is querying the database.
Query 2: If you want to explicitly cast the VARCHAR2 to a specific length then you can use the CAST( your_value AS VARCHAR2(10) ) function to cast it to a length of 10 but, as you can see below, it does not affect the output from DUMP as the returned value already had a length of 10.
SELECT '20180818' AS input,
CAST( jbmdate( '20180818' ) AS VARCHAR2(10) ) AS dt,
DUMP( CAST( jbmdate( '20180818' ) AS VARCHAR2(10) ) ) AS "dump"
FROM DUAL
Results:
| INPUT | DT | dump |
|----------|------------|---------------------------------------------|
| 20180818 | 18.08.2018 | Typ=1 Len=10: 49,56,46,48,56,46,50,48,49,56 |
A function only defines the base type of its return value (in this case, VARCHAR2). It can't define a more specific length to influence the display format used by your GUI.
Applications will vary in the way they display strings. For example, PL/SQL Developer will display the output in the compact form you are expecting, and so will Oracle Live SQL.
It should look like this
...
but it looks like this when used in the gui.
...
So the real problem is not the gui itself but the sql
I can't see how you reached that conclusion, as it seems clear that the issue is in the GUI (SQuirreL SQL Client?) Perhaps you could try it in a different tool.
What type of variables should select user from dual return?
If is not varchar, how can I cast to varchar(30) or varchar2(30)?
Does a method exist which returns the current user name better than it?
According to:
select dump(user) from dual;
it is type 1, which is varchar2. (Or nvarchar2, based just on that number.) The length - the number of bytes - varies, of course, as it's varchar.
The documentation for the user function also says:
This function returns a VARCHAR2 value.
You can cast the user to varchar2(30):
select cast(user as varchar2(30)) from dual;
but according to dump it's exactly the same afterwards. You'd only see a difference if the username was longer than 30 characters to start with; then it would be truncated. However, the docs also say:
Oracle Database compares values of this function with blank-padded comparison semantics.
Which means that if my username is, say, STACKOVERFLOW then both of these return data:
select * from dual where user = 'STACKOVERFLOW';
select * from dual where user = 'STACKOVERFLOW ';
The blank-padded comparison means that it's padding the result of user to the length of the literal it's being compared with.
Once you cast the result that is no longer true as it reverts to nonpadded comparison:
select * from dual where cast(user as varchar2(30)) = 'STACKOVERFLOW';
gets a row back but this does not:
select * from dual where cast(user as varchar2(30)) = 'STACKOVERFLOW ';
An alternative is to use sys_context():
select sys_context('USERENV', 'SESSION_USER') from dual;
which also returns varchar2, and again that be cast to little effect; and this uses nonpadded comparison, so again
select * from dual where sys_context('USERENV', 'SESSION_USER') = 'STACKOVERFLOW'
finds data but this does not:
select * from dual where sys_context('USERENV', 'SESSION_USER') = 'STACKOVERFLOW '
... with or without explicit casting.
I was trying the TO_DATE function. Specifically, I noted that the following queries
1. SELECT TO_CHAR(TO_DATE('01-01-2015','DD-MM-YYYY'),'DD-MON-YY') FROM DUAL
2. SELECT TO_DATE('01-01-2015','DD-MM-YYYY') FROM DUAL
have the same output: 01-JAN-2015.
Why does the TO_DATE function return the month in its abbreviated form?
My expected output for the second query is something like 01-01-2015 (simply, a TYPE conversion, NOT a format conversion).
Am I wrong?
Thanks
Dates do not have a format - they are represented by 7- or 8-bytes.
SELECT DUMP( SYSDATE ) FROM DUAL;
Might output:
Typ=13 Len=8: 220,7,11,26,16,41,9,0
This format is very useful for computers to compare dates but not so useful to people; so, when the SQL client (SQL/plus, SQL Developers, TOAD, etc) displays a date it does not display the the bytes but displays it as a string.
It does this by making an implicit call to TO_CHAR() (or some other internal method of stringifying dates) and uses a default format mask to perform this conversion.
SQL/Plus and SQL Developer will use the user's session parameter NLS_DATE_FORMAT to perform this conversion - see this answer regarding this.
So your second query is implicitly being converted to do something approaching this (but, almost certainly, more efficiently):
SELECT TO_CHAR(
TO_DATE('01-01-2015','DD-MM-YYYY'),
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
)
FROM DUAL
The default output format of DATE value, resp TO_DATE() function is set by NLS_DATE_FORMAT value. You can verify it with this query:
SELECT *
FROM V$NLS_PARAMETERS
WHERE PARAMETER = NLS_DATE_FORMAT';
You can change it on session level for example with
alter session set NLS_DATE_FORMAT = 'DD-MM-YYYY';
The output format of TO_CHAR is not correct, try:
SELECT TO_CHAR(TO_DATE('01-01-2015','DD-MM-YYYY'),'DD-MM-YYYY') FROM DUAL;
Oracle TO_DATE: is used to convert a character string to a date format.
and related to your concern; you need to alter your session like below:
alter session set nls_date_format='DD-MM-YYYY'
in your apps right after the connect.
So now if you run again your query :
SELECT TO_DATE ('01-01-2015', 'DD-MM-YYYY')
FROM DUAL;
the result would be as expected:
01-01-2015
Hope that will help.