Oracle REGEXP_LIKE ignore CASE SENSITIVITY - oracle

We are trying the following request in Oracle Database 19.3 and the result is ever like the case sensitivity was ignores.
select 1 from dual where regexp_like('CHIEN', '[a-z]+', 'c');
And the result of the request is
1
Even with:
ALTER SESSION SET NLS_COMP=ANSI;
ALTER SESSION SET NLS_SORT=GERMAN_AI;
We are thinking that's come from a NLS parameter but we don't found which one.
We have those parameters:
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_calendar string GREGORIAN
nls_comp string BINARY
nls_currency string €
nls_date_format string DD/MM/RR
nls_date_language string FRENCH
nls_dual_currency string €
nls_iso_currency string FRANCE
nls_language string FRENCH
nls_length_semantics string BYTE
nls_nchar_conv_excp string FALSE
nls_numeric_characters string ,
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string FRENCH
nls_territory string FRANCE
nls_time_format string HH24:MI:SSXFF
nls_timestamp_format string DD/MM/RR HH24:MI:SSXFF
nls_timestamp_tz_format string DD/MM/RR HH24:MI:SSXFF TZR
nls_time_tz_format string HH24:MI:SSXFF TZR
And our NLS_LANG is set to French_France.AL32UTF8

Finally I found the solution.
The problem was with NLS_SORT=FRENCH (or any linguistic sort)
NLS_SORT=FRENCH => AaBbCcDdEeFfGgHhIiJjKkLlMmNn .... Z
And when we are lookup for regular expression [a-z], we include BCDE ... Z
The solution is to set NLS_SORT=BINARY
In my case, I set environment variable NLS_SORT=BINARY. Without that, Oracle take the default NLS_SORT value that correspond to NLS_LANG.

Related

How to read the length of a string in Oracle?

I created the following table with one text column:
create table table1 (
col1 varchar2(20)
);
Then I inserted one Polish letter to it:
insert into table1 values ('ą')
How can I obtain the number of characters in this string? It should be 1, but all functions that I know return other results:
LENGTH(COL1) -> 2,
LENGTHC(COL1) -> 2,
LENGTH2(COL1) -> 2,
LENGTH4(COL1) -> 2,
LENGTHB(COL1) -> 6.
The SELECT * FROM NLS_DATABASE_PARAMETERS; returns:
PARAMETER VALUE
---------------------------------
NLS_RDBMS_VERSION 18.0.0.0.0
NLS_NCHAR_CONV_EXCP FALSE
NLS_LENGTH_SEMANTICS BYTE
NLS_COMP BINARY
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_CHARACTERSET AL32UTF8
NLS_ISO_CURRENCY AMERICA
NLS_TERRITORY AMERICA
NLS_LANGUAGE AMERICAN
... ...
You can check it on: dbfiddle.uk.
It is most likely a bug with the version of Oracle you are running the query on or an issue with the character being encoded on the web server.
I have almost all of the same NLS parameters on my system except I am on Oracle 19 instead of 18.
Even on livesql.oracle.com it returns the results as you would expect but again, that database is on Oracle 19.

DBeaver/Oracle wrong datetime pattern includes .0 at end

Using DBeaver and Oracle, select querys shows date in a wrong format, which always includes .0 at the end, like 2019-05-17 16:10:47.0.
To update/insert any date column in a table, on DBeaver editor, doesn't matter the date pattern I try, throws:
ORA-01861: literal does not match format string
SELECT sysdate FROM dual
-- returns date with .0: 2019-05-17 17:21:11.0
SELECT TO_CHAR(sysdate, 'YYYY-MM-DD HH24:MI:SS') FROM dual
-- returns ok: 2019-05-17 17:21:11
It's ok on Oracle SQL Developer.
I also tried removing SSXFF from NLS_PARAMETERS, but doesn't seem to work:
SELECT * FROM v$nls_parameters
--NLS_DATE_FORMAT DD/MM/RR
--NLS_TIME_FORMAT HH24:MI:SSXFF
--NLS_TIMESTAMP_FORMAT DD/MM/RR HH24:MI:SSXFF
--NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
--NLS_TIMESTAMP_TZ_FORMAT DD/MM/RR HH24:MI:SSXFF TZR
alter session set NLS_TIME_FORMAT = 'HH24:MI:SS'
alter session set NLS_TIMESTAMP_FORMAT = 'DD/MM/RR HH24:MI:SS'
alter session set NLS_TIME_TZ_FORMAT = 'HH24:MI:SS TZR'
alter session set NLS_TIMESTAMP_TZ_FORMAT = 'DD/MM/RR HH24:MI:SS TZR'
Environment:
Windows 10
Oracle Database 12c 12.2.0.1.0 - 64bit
DBeaver 6.0.3
Driver OJDBC7
Make sure on DBeaver Preferences > Data Formats > "Disable date / time formatting" option is unchecked.
Thats allows to use client-side formats on insert/update actions.

Set NLS_SORT and NLS_COMP in oracle

I am trying to set NLS_COMP and NLS_SORT for the current session to check if it will make a difference with regards to some SQL query I am running that is case sensitive, for some reason the parameters will not change
what am I doing wrong?
SELECT * FROM nls_database_parameters where parameter in ('NLS_COMP','NLS_SORT');
>>> NLS_SORT BINARY
>>> NLS_COMP BINARY
SELECT * FROM nls_instance_parameters where parameter in ('NLS_COMP','NLS_SORT');
>>> NLS_SORT NULL
>>> NLS_COMP BINARY
ALTER SESSION SET NLS_COMP=LINGUISTIC;
>>>session SET altered.
ALTER SESSION SET NLS_SORT=BINARY_CI;
>>>session SET altered.
SELECT * FROM nls_database_parameters where parameter in ('NLS_COMP','NLS_SORT');
>>> NLS_SORT BINARY
>>> NLS_COMP BINARY
SELECT * FROM nls_instance_parameters where parameter in ('NLS_COMP','NLS_SORT');
>>> NLS_SORT NULL
>>> NLS_COMP BINARY
You are setting the session values but reading the system ones. Try reading from NLS_SESSION_PARAMETERS:
SELECT *
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

Oracle database timestamp to timestamp with timezone

Need help in inserting the data from timestamp , to timestamp with zone.
create table foo ( tswtz TIMESTAMP WITH TIME ZONE);
SQL:>insert into foo values(systimestamp)
TSWTZ
---------------------------------------
09-08-16 11:39:21.199780000 AM +05:30
create table foo1 (test_dt timestamp)
insert into foo1 values(systimestamp)
TEST_DT
--------------------------------
09-08-16 11:40:55.242754000 AM
Now , there is a scenario, where i need to insert the values of foo1 to foo.
I have used the below command,
insert into foo (TSWTZ) (select CAST(TEST_DT AS TIMESTAMP WITH TIME ZONE) from foo1)
The select value displayed it as
09-08-16 11:40:55.242754000 AM ASIA/CALCUTTA
But it should display it as
09-08-16 11:40:55.242754000 AM +05:30.
Can you please help me on how to do that, without alter command ?
You need to alter your NLS parameters to get the result. Please read the oracle documentation as well [https://docs.oracle.com/cd/B19306_01/server.102/b14225/ch4datetime.htm][1]
Try setting:
NLS_TIMESTAMP_TZ_FORMAT = DD-MON-RR HH.MI.SSXFF AM TZR
and NLS_TIMESTAMP_FORMAT = DD-MON-RR HH.MI.SSXFF AM
and NLS_TIME_TZ_FORMAT = HH.MI.SSXFF AM TZR
and NLS_TIME_FORMAT = HH.MI.SSXFF AM
Function SYSTIMESTAMP returns current time in time zone of your database server operating system, in your case +05:30.
When you cast from TIMESTAMP (without any time zone information) to TIMESTAMP WITH TIME ZONE then Oracle takes your SESSIONTIMEZONE - unless you specify the time zone explicitly.
Obviously in your case the SESSIONTIMEZONE is set to Asia/Calcutta.
In order to get desired result you can do either
ALTER SESSION SET TIME_ZONE = '+05:30';
or
SELECT CAST((TEST_DT AT TIME ZONE '+05:30') AS TIMESTAMP WITH TIME ZONE)
FROM ...
Note, time zone Asia/Calcutta is different than +05:30, although the offset is the same. Region names like Asia/Calcutta considers daylight saving times (which does not apply for Asia/Calcutta), UTC offsets like +05:30 do not consider daylight saving times.

what does affect Oracle's determination of string expressions datatype?

I'm observing a difference in how Oracle determines a datatype of string expressions on one particular Oracle instance. The most striking example is the datatype of an empty string: on all instances but one the datatype is char(0); on that exceptional one it's char(32).
The following script illustrates this: it parses a simple statement SELECT '' FROM dual and describes the column.
===
SET SERVEROUTPUT ON
DECLARE
c NUMBER;
col_cnt INTEGER;
rec_tab DBMS_SQL.DESC_TAB;
BEGIN
DBMS_OUTPUT.PUT_LINE('Testing the datatype of an empty string:');
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'SELECT '''' as empty_string FROM dual', DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
DBMS_OUTPUT.PUT_LINE('max length = ' || rec_tab(1).col_max_len);
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
===
It returns 32 on this specific instance and 0 on all the others. The following is the result of querying nls_database_parameters on that particular instance:
PARAMETER VALUE
--------------- ---------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET WE8MSWIN1252
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_RDBMS_VERSION 11.1.0.7.0
NLS_CSMIG_SCHEMA_VERSION 5
It does not differ from all the other instances. The only thing that is different is the installed TDE option. Unfortunately I don't have an instance with this option installed at hand and cannot test it there...
My question is if anyone knows of the factors which may influence the way Oracle determines the datatype of string expressions. The case with empty strings is not the only one, but it's the most critical as we have a legacy application that issues lots of SELECTs with empty strings without casting them to a specific datatype and that difference in Oracle's behaviour stops the application from working. Any input would be appreciated!
Konstantin
Very curious, I can't replicate this on 9.2.0.1.0, 10.2.0.1.0, 11.1.0.6.0 or 11.2.0.1.0 and they all have near identical parameters (UK not US).
The only possibility that I can think of is that someone at some point has logged onto sys and played about with ( altered ) dual. Obviously I've obscured the server name and pw...
[oracle#server ~]$ sqlplus -S "sys/pw as sysdba"
Session altered.
desc dual
Name Null? Type
----------------- -------- --------------------------------------------
DUMMY VARCHAR2(1)
set echo on
select dbms_lob.substr(dbms_metadata.get_ddl('TABLE','DUAL')) from dual;
DBMS_LOB.SUBSTR(DBMS_METADATA.GET_DDL('TABLE','DUAL'))
--------------------------------------------------------------------------------
CREATE TABLE "SYS"."DUAL"
( "DUMMY" VARCHAR2(1)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 16384 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DE
FAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSTEM"
Your output should look like the above. If it's something different then that would explain the strangeness.

Resources