casting variables and select username in oracle 12c - oracle

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.

Related

Getting error while running session as not avalid month

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;

What is the benefit of NULL values in Oracle?

I'm trying to understand how Oracle handles NULL values. This is really more of a request for confirmation of what I've already discovered, to make sure I haven't overlooked something obvious. Below are scripts to confirm that Oracle handles NULL values the same as it handles a blank string. If such is the case, then pray tell why would any Oracle database be developed to ever allow a field to be NULL, other than to introduce obfuscation to an index when querying against it (i.e. ... WHERE NVL(FieldName,'Default Value') != 'test')???
-- Returns only 2 rows
-- Oracle doesn't differentiate from blank strings and NULL values
SELECT NULL AS Test_Nulls from dual
UNION
SELECT '' AS Test_Nulls from dual
UNION
SELECT 'Test' AS Test_Nulls from dual;
-- Returns "X"
-- Further proof Oracle doesn't differentiate from blank strings and NULL values
SELECT 'X' AS Test_Nulls
FROM dual
WHERE '' is NULL;
-- Returns "X"
-- Even further proof Oracle doesn't differentiate from blank strings and NULL values
SELECT NVL('','X') AS Test_Nulls
FROM dual;
-- Returns 3 rows
-- Oracle recognizes <Carriage Return> + <Line Feed>
SELECT '' AS Returned from dual
UNION
SELECT '
' AS Returned FROM dual
UNION
SELECT 'Test' AS Returned FROM dual;
Simple Answer: For any new database design work I do in Oracle, I will set all my varchar2 and nvarchar2 and char2 and nchar2 fields to not allow NULL and to have a default value of an empty string. I have always been suspicious of the naming convention of adding a "2" suffix, and the fact that it is not a common field type to other database platforms. To me, it seems like a last-minute desperate means that Oracle handled a situation in their early days like, "Oh well, ... we can't make it right, so we'll just give it a new name!" That's my 2-cents on this matter.

Declaring and using variables in PL-SQL

I am new to PL-SQL. I do not understand why I am getting the error "PLS-00428: an INTO clause is expected in this SELECT statement"
What I'm trying to accomplish is to create a variable c_limit and load it's value. I then want to use that variable later to filter data.
Basically I am playing around in the demo db to see what I can/can't do with PL-SQL.
The code worked up to the point that I added "select * from demo_orders where CUSTOMER_ID = custID;"
declare
c_limit NUMBER(9,2);
custID INT;
BEGIN
custID := 6;
-- Save the credit limit
select credit_limit INTO c_limit
from demo_customers cust
where customer_id = custID;
select * from demo_orders where CUSTOMER_ID = custID;
dbms_output.Put_line(c_limit);
END;
If you are using a SQL SELECT statement within an anonymous block (in PL/SQL - between the BEGIN and the END keywords) you must select INTO something so that PL/SQL can utilize a variable to hold your result from the query. It is important to note here that if you are selecting multiple columns, (which you are by "SELECT *"), you must specify multiple variables or a record to insert the results of your query into.
for example:
SELECT 1
INTO v_dummy
FROM dual;
SELECT 1, 2
INTO v_dummy, v_dummy2
FROM dual;
It is also worth pointing out that if your SELECT * FROM.... will return multiple rows, PL/SQL will throw an error. You should only expect to retrieve 1 row of data from a SELECT INTO.
Looks like the error is from the second select query.
select * from demo_orders where CUSTOMER_ID = custID;
PL-SQL won't allow a standalone sql select query for info.
http://pls-00428.ora-code.com/
You need to do some operation with the second select query

How to use repalce function to change string from query in oracle

select replace (SELECT TO_CHAR(CURRENT_TIMESTAMP) FROM DUAL,CURRENT_TIMESTAMP,'2015-03-10 11:45:15') As result from dual;
I want to change CURRENT_TIMESTAMP with '2015-03-10 11:45:15' but oracle gives
error.However if you remove select statement then it works fine I mean
select replace (TO_CHAR(CURRENT_TIMESTAMP),CURRENT_TIMESTAMP,'2015-03-10 11:45:15') As result from dual;
this works fine but I have so long query and CURRENT_TIMESTAMP coming several times and I want to replace it with given string
It is working fine in mysql I want it in oracle
You need to put the brackets around the subquery:
select replace ((SELECT TO_CHAR(CURRENT_TIMESTAMP) FROM DUAL),CURRENT_TIMESTAMP,'2015-03-10 11:45:15') As result
from dual;
However, this is badly written. Your TO_CHAR(CURRENT_TIMESTAMP) has no format mask, which means your conversion of the timestamp to the string is reliant on your nls settings. This is bad practice.
Also, the CURRENT_TIMESTAMP in the second parameter of your replace statement is undergoing an implicit conversion into a string, again relying on your nls settings.
If I were you, I'd write it as:
select replace ((SELECT TO_CHAR(CURRENT_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss') FROM DUAL),
TO_CHAR(CURRENT_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss'),
'2015-03-10 11:45:15') As result
from dual;

Oracle: Show special text if field is null

I would like to write a select where I show the value of the field as normal except when the field is null. If it is null I'd like to show a special text, for example "Field is null". How would I best do this?
// Oracle newbie
I like to use function COALESCE for this purpose. It returns the first non-null value from given arguments (so you can test more than one field at a time).
SELECT COALESCE(NULL, 'Special text') FROM DUAL
So this would also work:
SELECT COALESCE(
First_Nullable_Field,
Second_Nullable_Field,
Third_Nullable_Field,
'All fields are NULL'
) FROM YourTable
Just insert the NVL PL/SQL function into your query
SELECT NVL(SOMENULLABLEFIELD,'Field Is Null') SOMENULLABLEFIELD
FROM MYTABLE;
More detail here : http://www.techonthenet.com/oracle/functions/nvl.php
You could also use DECODE:
select value, decode(value, NULL, 'SPECIAL', value) from
(select NULL value from dual
union all
select 2 value from dual
)

Resources