Oracle NLS_SORT not working via ALTER SESSION? - sql

Using 'alter session set nls_sort' does not seem to be working for me. I am using SQLPlus v11.2.0.3.0 x64 and trying to apply the simple steps for 'Example 9-10 NLS_SORT Affects Linguistic Sort Order' found in the Oracle documentation at http://docs.oracle.com/cd/E18283_01/appdev.112/e10766/tdddg_globalization.htm#CACJEJIB
CREATE TABLE temp (name VARCHAR2(15));
INSERT INTO temp (name) VALUES ('laguna');
INSERT INTO temp (name) VALUES ('llama');
INSERT INTO temp (name) VALUES ('loco');
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_SORT';
Result: BINARY
SELECT * FROM temp ORDER BY name;
Result:
NAME
---------------
laguna
llama
loco
ALTER SESSION SET NLS_SORT=SPANISH_M;
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_SORT';
Result: SPANISH_M
SELECT * FROM temp ORDER BY name;
Results are the same:
NAME
---------------
laguna
llama
loco
According to the doco, the sort order above should have changed but it did not. But, if I apply the NLS_SORT as part of the query itself I get the correct resutls:
SELECT * FROM temp ORDER BY NLSSORT(name, 'NLS_SORT=SPANISH_M');
Result:
NAME
---------------
laguna
loco
llama
What am I missing here? Thx in advance.

This was resolved whe I uninstalled Oracle v11.2.0.3.0 and installed v12.1.0.1.0. Truth be told, I can't rule out that it may have just been a problem with our wrapper/configuration of the v11.2.0.3.0 Oracle installer or Oracle itself. Thx for all the post just the same.

The solution is:
1) Go to the REGISTRY (run regedit)
2) Find HKEY_LOCAL_MACHINE/Software/ORACLE
3) Change NLS_LANG
I changed it to
AMERICAN_AMERICA.AR8MSWIN1256
dont forget that you must change all the NLS_LANG in part 2.
now you can login to your database and test it.

Related

How to separate SQL variable inside a string

In my SQL script I can define variable like:
DEFINE x=100;
and use it like:
CREATE TABLE A&x AS ...;
the result will be CREATE TABLE A100 AS ... (concatenated string).
But I'd like to get CREATE TABLE A100B AS ... in similar query (B suffix):
CREATE TABLE A&xB AS ...;
But Oracle/SQL understands there is xB variable
How to separate variable (name) inside SQL:
CREATE TABLE A&{x}B AS ...;
This does not work!
(e.g. like ${x} i PHP)
It is just a tiny, little dot.
SQL> define x=100
SQL> create table a&x.b as select * from dual;
old 1: create table a&x.b as select * from dual
new 1: create table a100b as select * from dual
Table created.
SQL> select * from a100b;
D
-
X
SQL>
Here, in case you missed it:
create table a&x.b
^
|
here
What's the point? The SQLPlus concatenation character. By default, it is a dot. It tells SQLPlus where the variable name ends.
If you ask for more help:
SQL> help set
SET
---
Sets a system variable to alter the SQL*Plus environment settings
for your current session. For example, to:
- set the display width for data
- customize HTML formatting
- enable or disable printing of column headings
- set the number of lines per page
SET system_variable value
where system_variable and value represent one of the following clauses:
APPI[NFO]{OFF|ON|text} NEWP[AGE] {1|n|NONE}
ARRAY[SIZE] {15|n} NULL text
AUTO[COMMIT] {OFF|ON|IMM[EDIATE]|n} NUMF[ORMAT] format
<snip>
---------------------
CON[CAT] {.|c|ON|OFF} [FOR[MAT] {WRA[PPED] |
---------------------
Here it is!

How to fetch case sensitive data without using Upper, Lower, init cap functions in oracle

I have a transaction table in which there is a column trans_mode which stores transaction mode for the transactions. Transaction mode contains one of the following values.
trans_mode
web
app
APP
APP
wEb
and there are are many more possibilities as trans_mode is varchar column.
I want to write a simple select statement like
select count(trans_mode) from tab where trans_mode='web';
or
select count(trans_mode) from tab where trans_mode='Web';
Now, I do not want to use any condition like upper(trans_mode)='WEB' or lower(trans_mode)='web' or any regular expression, and output required is the count of web transactions ignoring the case.
I think we can achieve the same using "column format" when defining trans_mode column or by using some other method. However not sure. Please suggest.
You can't do that with a "column format", but you can change your current sessions' NLS behaviour:
ALTER SESSION SET nls_comp = Linguistic;
ALTER SESSION SET nls_sort = binary_CI;
select *
from tab
where trans_mode = 'app';
results in:
TRANS_MODE
----------
app
APP
APP
Online example: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=a0196bf8031e5c612b9a9f6a2de870e4
If you need the comparison to honor language specific comparison rules (e.g. ß and SS should be treated the same in German), you can do that as well:
insert into tab values ('große');
insert into tab values ('GROSSE');
ALTER SESSION SET nls_comp = Linguistic;
ALTER SESSION SET nls_sort = XGerman_CI;
select *
from tab
where trans_mode = 'große'
returns:
TRANS_MODE
----------
große
GROSSE
Starting with Oracle 12.2 you can also use the collate option:
select *
from tab
where trans_mode = 'app' collate binary_ci
Use COLLATE:
select count(trans_mode) from tab where trans_mode='Web' COLLATE SQL_Latin1_General_CP1_CI_AS
Will return web and wEb
In Oracle 12.2 you can use collate binary_ci at column level.
CREATE TABLE transactions (
id NUMBER,
trans_mode VARCHAR2(4 CHAR) COLLATE BINARY_CI,
CONSTRAINT t1_pk PRIMARY KEY (id)
);
insert into transactions values(1,'web');
insert into transactions values(2,'app');
insert into transactions values(1,'Web');
insert into transactions values(1,'weB');
commit;
select count(0) from transactions where trans_mode = 'web' ;
Reference link:
https://oracle-base.com/articles/12c/column-level-collation-and-case-insensitive-database-12cr2#column-level

DB2 9.7 SQL syntax, what am I doing wrong?

For one reason or other which are out of my control I am attempting to simply pull data over the past 12 months. However, essentially down to the size of data, I have to query each day into a temp table and go from there. Now I'm a newbie to scripting in DB2, but not SQL in general, so I've tried the code below (the logic seems fine to me).
Initially I'm was just interested in how many records will be generated, but ideally I'd want to run the second SELECT code. I've been using Data Studio, but I believe to export the data I would need to run this via CLP. Now my issues are that I'm missing something within syntax that I can't figure out and it's doing my head in. It's most likely something very basic or I'm just doing it totally wrong.
If I try the SELECT COUNT(*) code I'm getting these errors: -
Multiple markers at this line
- DB2 for Linux, UNIX, and Windows: "" was expected after "FROM".
- DB2 for Linux, UNIX, and Windows: "." is invalid.
If I try the other SELECT code I'm getting these errors: -
DB2 for Linux, UNIX, and Windows: "" was expected instead of "SELECT MARKET_ID,
SUPER_REGION,
REGION,
MARKET,
POSA,
DEST_ID,
DEST_NAME,
DEST_TYPE,
STAT...
DB2 for Linux, UNIX, and Windows: "," was expected after "FROM".
DB2 for Linux, UNIX, and Windows: "," was expected after "GROUP"
I just don't get it. Can someone please help? The SESSION.l12_Dest table also doesn't seem to be available afterwards for me to try looking at the table manually.
Code: -
--<ScriptOptions statementTerminator="#"/>
CREATE OR REPLACE PROCEDURE HWW.DM_CHECKLIST()
LANGUAGE SQL
BEGIN
DECLARE GLOBAL TEMPORARY TABLE SESSION.L12_DEST
(
ACTUAL_DATE DATE,
MARKET_ID INTEGER,
SUPER_REGION VARCHAR (100),
REGION VARCHAR (100),
MARKET VARCHAR (100),
POSA VARCHAR (100),
DEST_ID INTEGER,
DEST_NAME VARCHAR (100),
DEST_TYPE VARCHAR (30),
STATUS_CODE SMALLINT,
VISITORS INTEGER
)
ON COMMIT PRESERVE ROWS NOT LOGGED;
COMMIT;
FOR V_ROW AS
SELECT ACTUAL_DATE
FROM DM.DATE_DIM
WHERE ACTUAL_DATE
BETWEEN (CURRENT_DATE - 12 MONTHS) - DAY((CURRENT_DATE - 12 MONTHS)) DAYS + 1 DAYS
AND LAST_DAY((CURRENT_DATE - 1 MONTHS))
DO
INSERT INTO SESSION.L12_DEST
SELECT B.ACTUAL_DATE,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_ID,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_SUPER_REGN_NAME,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_REGN_NAME,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_NAME,
S.SITE_CNTRY_NAME,
Z.HCOM_SRCH_DEST_ID,
Z.HCOM_SRCH_DEST_NAME,
Z.HCOM_SRCH_DEST_TYP_NAME,
LZ.STATUS_CODE,
COUNT(DISTINCT(F.VISITOR_KEY))AS VISITORS
FROM DM.LODG_DEMAND_FACT F
INNER JOIN DM.V_HCOM_SRCH_DEST_DIM Z
ON F.HCOM_SRCH_DEST_KEY = Z.HCOM_SRCH_DEST_KEY
INNER JOIN DM.DATE_DIM B
ON F.LOCAL_DEMAND_DATE_KEY = B.DATE_KEY
INNER JOIN DM.SITE_DIM S
ON S.SITE_KEY = F.SITE_KEY
LEFT JOIN LZ.LZ_HCM_DESTINATION LZ
ON Z.HCOM_SRCH_DEST_ID = LZ.DESTINATION_INT_ID
WHERE F.BRAND_KEY = 101
AND B.ACTUAL_DATE = V_ROW.ACTUAL_DATE
GROUP BY B.ACTUAL_DATE,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_ID,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_SUPER_REGN_NAME,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_REGN_NAME,
Z.HCOM_SRCH_DEST_PROPERTY_MKT_NAME,
S.SITE_CNTRY_NAME,
Z.HCOM_SRCH_DEST_ID,
Z.HCOM_SRCH_DEST_NAME,
Z.HCOM_SRCH_DEST_TYP_NAME,
LZ.STATUS_CODE;
END FOR;
--SELECT COUNT(*) FROM SESSION.L12_DEST;
--EXPORT TO C:\TEMP\MARKETS.TXT OF DEL
SELECT MARKET_ID,
SUPER_REGION,
REGION,
MARKET,
POSA,
DEST_ID,
DEST_NAME,
DEST_TYPE,
STATUS_CODE,
SUM(VISITORS)
FROM SESSION.L12_DEST
GROUP BY MARKET_ID,
SUPER_REGION,
REGION,
MARKET,
POSA,
DEST_ID,
DEST_NAME,
DEST_TYPE,
STATUS_CODE;
END #
I don't think you can do a bare select statement in a stored proc (at least in DB2).
When I try this I get the same results: the most unhelpful error message ever. (thanks IBM)
But, if I put some valid statement after the END FOR; there isn't a problem.
If you want a stored proc to do a select and show you the answer do something like this:
CREATE OR REPLACE PROCEDURE DM_CHECKLIST()
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE RS CURSOR FOR SELECT COUNT(*) FROM sysibm.sysdummy1;
OPEN RS;
END#
The interesting thing is the DYNAMIC RESULT SETS 1 business. That tells the executor that we will have a result set returned and to show it in the command line interface (cli).
You can have as many result sets as you like. You will see the results on the cli, or you can get them pragmatically.
I did try the EXPORT command and it didn't seem to work.
EXPORT TO "C:\TEMP\MARKETS.TXT" OF DEL SELECT COUNT(*) FROM sysibm.sysdummy1;
It looks like you aren't allowed to use EXPORT in a stored proc, as it is a DB2 command and not a SQL statement. I wouldn't be surprised if there is some way to do it, but not this way.
To use the EXPORT utility in a stored procedure, you have to wrap it in the ADMIN_CMD procedure:
create procedure dm_checklist()
language sql
begin
declare global temporary table results (...)
on commit preserve rows;
-- Steps to build / populate your temporary table
call sysproc.admin_cmd('export to C:\file.del of del select * from session.results');
end

BLOB to String, SQL Server

I have a text string stored as a BLOB data type in a database. I want to extract it by an SQL select query, but I have problems converting/casting from BLOB to readable text.
I've tried e.g.
select convert(nvarchar(40),convert(varbinary(40),BLOBTextToExtract))
from [NavisionSQL$Customer]
I guess I need something similar, but I can't figure out exactly what I need to do the conversion. Can somebody please give me some directions?
Regards
The accepted answer works for me only for the first 30 characters.
This works for me:
select convert(varchar(max), convert(varbinary(max),myBlobColumn)) FROM table_name
Problem was apparently not the SQL server, but the NAV system that updates the field. There is a compression property that can be used on BLOB fields in NAV, that is not a part of SQL Server. So the custom compression made the data unreadable, though the conversion worked.
The solution was to turn off compression through the Object Designer, Table Designer, Properties for the field (Shift+F4 on the field row).
After that the extraction of data can be made with e.g.:
select convert(varchar(max), cast(BLOBFIELD as binary))
from Table
Thanks for all answers that were correct in many ways!
It depends on how the data was initially put into the column. Try either of these as one should work:
SELECT CONVERT(NVarChar(40), BLOBTextToExtract)
FROM [NavisionSQL$Customer];
Or if it was just varchar...
SELECT CONVERT(VarChar(40), BLOBTextToExtract)
FROM [NavisionSQL$Customer];
I used this script to verify and test on SQL Server 2K8 R2:
DECLARE #blob VarBinary(MAX) = CONVERT(VarBinary(MAX), 'test');
-- show the binary representation
SELECT #blob;
-- this doesn't work
SELECT CONVERT(NVarChar(100), #blob);
-- but this does
SELECT CONVERT(VarChar(100), #blob);
Can you try this:
select convert(nvarchar(max),convert(varbinary(max),blob_column)) from table_name
Found this...
bcp "SELECT top 1 BlobText FROM TableName" queryout "C:\DesinationFolder\FileName.txt" -T -c'
If you need to know about different options of bcp flags...
http://msdn.microsoft.com/en-us/library/ms162802.aspx
CREATE OR REPLACE FUNCTION HASTANE.getXXXXX(p_rowid in rowid) return VARCHAR2
as
l_data long;
begin
select XXXXXX into l_data from XXXXX where rowid = p_rowid;
return substr( l_data, 1, 4000);
end getlabrapor1;

Informix: Select null problem

Using Informix, I've created a tempory table which I am trying to populate from a select statement. After this, I want to do an update, to populate more fields in the tempory table.
So I'm doing something like;
create temp table _results (group_ser int, item_ser int, restype char(4));
insert into _results (group_ser, item_ser)
select
group_ser, item_ser, null
from
sometable
But you can't select null.
For example;
select first 1 current from systables
works but
select first 1 null from systables
fails!
(Don't get me started on why I can't just do a SQL Server like "select current" with no table specified!)
You don't have to write a stored procedure; you simply have to tell IDS what type the NULL is. Assuming you are not using IDS 7.31 (which does not support any cast notation), you can write:
SELECT NULL::INTEGER FROM dual;
SELECT CAST(NULL AS INTEGER) FROM dual;
And, if you don't have dual as a table (you probably don't), you can do one of a few things:
CREATE SYNONYM dual FOR sysmaster:"informix".sysdual;
The 'sysdual' table was added relatively recently (IDS 11.10, IIRC), so if you are using an older version, it won't exist. The following works with any version of IDS - it's what I use.
-- #(#)$Id: dual.sql,v 2.1 2004/11/01 18:16:32 jleffler Exp $
-- Create table DUAL - structurally equivalent to Oracle's similarly named table.
-- It contains one row of data.
CREATE TABLE dual
(
dummy CHAR(1) DEFAULT 'x' NOT NULL CHECK (dummy = 'x') PRIMARY KEY
) EXTENT SIZE 8 NEXT SIZE 8;
INSERT INTO dual VALUES('x');
REVOKE ALL ON dual FROM PUBLIC;
GRANT SELECT ON dual TO PUBLIC;
Idiomatically, if you are going to SELECT from Systables to get a single row, you should include 'WHERE tabid = 1'; this is the entry for Systables itself, and if it is missing, the fact that your SELECT statement does return any data is the least of your troubles. (I've never seen that as an error, though.)
This page says the reason you can't do that is because "NULL" doesn't have a type. So, the workaround is to create a sproc that simply returns NULL in the type you want.
That sounds like a pretty bad solution to me though. Maybe you could create a variable in your script, set it to null, then select that variable instead? Something like this:
DEFINE dummy INT;
LET dummy = NULL;
SELECT group_ser, item_ser, dummy
FROM sometable
SELECT group_ser, item_ser, replace(null,null) as my_null_column
FROM sometable
or you can use nvl(null,null) to return a null for your select statement.
Is there any reason to go for an actual table? I have been using
select blah from table(set{1})
select blah from table(set{1})
is nice when you are using 10.x database. This statement doesn't touch database. The amount of read/write operations is equal to 0,
but
when you're using 11.x it will cost you at least 4500 buffer reads because this version of Informix creates this table in memory and executes query against it.
select to_date(null) from table;
This works when I want to get a date with null value
You can use this expression (''+1) on the SELECT list, instead of null keyword. It evaluates to NULL value of type DECIMAL(2,0).
This (''+1.0001) evaluates to DECIMAL(16,4). And so on.
If you want DATE type use DATE(''+1) to get null value of type DATE.
(''+1)||' ' evaluates to an empty string of type VARCHAR(1).
To obtain NULL value of type VARCHAR(1) use this expression:
DATE(''+1)||' '
Works in 9.x and 11.x.