Result like Oracle query in SQL Server 2016 - sql

In Oracle for e.g.
create table test1(Prod_Name varchar2(30))
insert into test1 values('CHANNEL')
insert into test1 values('SHELL')
insert into test1 values('_DISTRIBUTOR BELT')
select * from test1 order by prod_name asc
Select query gives the following result
Prod_Name
CHANNEL
SHELL
_DISTRIBUTOR BELT
but in SQL Server it giving following result
Prod_Name
_DISTRIBUTOR BELT
CHANNEL
SHELL
I want the result to be the same as Oracle in SQL Server so how to write query. To clarify, I want CHANNEL, SHELL, and _DISTRIBUTOR BELT row in last

In SQL Server you can force the collation when using COLLATE. Try this below script and you should get your expected output this way.
DEMO HERE
SELECT *
FROM test1
ORDER BY prod_name
COLLATE SQL_Latin1_General_CP850_BIN2

This is tricky. Oracle and SQL Server have different sorting rules. Oracle by default does binary sort, which is based on the numeric values of the characters defined by the character encoding scheme (this is the fastest method).
The underscore character (_) has ASCII code 95, while A-Z range from 65 to 90. Hence the results that you are seeing.
One way to produce the expected results is to do a linguistic sort: with this setting, characters are sorted independently of their numeric values in the character encoding scheme.
I played around with the parameters, and here is a solution that sorts as expected:
select * from test1 order by nlssort(prod_name, 'nls_sort = punctuation')
Demo on DB Fiddle
Please note that this will be slower than doing a binary sort.

Related

Using Regex to determine what kind of SQL statement a row is from a list?

I have a large list of SQL commands such as
SELECT * FROM TEST_TABLE
INSERT .....
UPDATE .....
SELECT * FROM ....
etc. My goal is to parse this list into a set of results so that I can easily determine a good count of how many of these statements are SELECT statements, how many are UPDATES, etc.
so I would be looking at a result set such as
SELECT 2
INSERT 1
UPDATE 1
...
I figured I could do this with Regex, but I'm a bit lost other than simply looking at everything string and comparing against 'SELECT' as a prefix, but this can run into multiple issues. Is there any other way to format this using REGEX?
You can add the SQL statements to a table and run them through a SQL query. If the SQL text is in a column called SQL_TEXT, you can get the SQL command type using this:
upper(regexp_substr(trim(regexp_replace(SQL_TEXT, '\\s', ' ')),
'^([\\w\\-]+)')) as COMMAND_TYPE
You'll need to do some clean up to create a column that indicates the type of statement you have. The rest is just basic aggregation
with cte as
(select *, trim(lower(split_part(regexp_replace(col, '\\s', ' '),' ',1))) as statement
from t)
select statement, count(*) as freq
from cte
group by statement;
SQL is a language and needs a parser to turn it from text into a structure. Regular expressions can only do part of the work (such as lexing).
Regular Expression Vs. String Parsing
You will have to limit your ambition if you want to restrict yourself to using regular expressions.
Still you can get some distance if you so want. A quick search found this random example of tokenizing MySQL SQL statements using regex https://swanhart.livejournal.com/130191.html

How to store the result of select statement into the temporary table in Oracle?

We can write select column1,column2 into #temp from tableName in SQL Server. But I am unable to write the same query in an Oracle database.
I want to store the result of select/insert/delete/update or any result set into a local temporary table in oracle database. How I can do this?
I am executing below query in my Oracle sql developer tool:
select * into #temp
from bmi;
but I am getting the error as follow please help to find this error.
when I execute the same query in Microsoft SQL Server it get executed & #temp table get created which is not present in the database but it can hold the data for that particular session. so i want same scenario in ORACLE database.
ORA-00911: invalid character
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual.
*Action:
Error at Line: 1 Column: 15
I want to store the result of select/insert/delete/update or any result set into a local temporary table in oracle database,How I can Do This?
You can't. Oracle doesn't have local temporary tables, it doesn't work like that. But it doesn't need to. Oracle has a very different internal model from SQL Server which means a lot of SQL Server practices are unnecessary in Oracle. (To be fair SQL Server has neat things which Oracle doesn't, like ANSI 92 Joins for DML.)
The key insight is: you don't want to store the result of select/insert/delete/update or any result set into a local temporary table. That is something you had to do in T-SQL to achieve the end goal of implementing some business logic. But what you actually wanted to do in SQL Server and what you want to do in Oracle is write some code which delivers value to your organisation.
So, with that mindset in place, what do you need to do?
If you want to loop round a result set then perhaps a Cursor Loop is what you're looking for?
for rec in ( select * from some_table
where the_date = date '2018-02-01' )
loop
...
If you want to work on some data prior to inserting it into a data then perhaps you should use a PL/SQL collection:
type l_recs is table of some_table%rowtype;
But maybe you just need to understand Oracle's Transaction Management model. A lot of things are possible in pure SQL without any need for procedural framework.
Create temporary table :
create global temporary table
results_temp (column1, column2)
on commit preserve rows;
and then insert to it from your table:
insert into results_temp (column1, column2 )
SELECT column1,column2
FROM source_table
create global temporary table temp_table_name
on commit preserve rows as select column1,column2,columnN from your_table;

How to manage order by in SQL server as compare to Sybase?

I'm migrating from SybaseIQ to SQL Server 2008, one major diffrence observer is in ORDER BY clause.
Created on table as create table test(name varchar(20))
Inserted some records:
insert into test values('Hi')
insert into test values('Toi')
insert into test values('>Toi')
insert into test values('iHh')
insert into test values('hi')
insert into test values('IhH')
insert into test values('1Hi')
insert into test values('2Hi')
Performed select operation on both SQL Server and Sybase as:
select * from test order by name desc
Result for Sybase is:
name
-------
iHh
hi
Toi
IhH
Hi
>Toi
2Hi
1Hi
And result for SQL server is:
name
-------
Toi
IhH
iHh
Hi
hi
2Hi
1Hi
>Toi
Why this order differ in SQL server and Sybase? How to manage order by in SQL server as compare to Sybase to get same result?
You can use the collation Latin1_General_BIN2 as the SQL server default collation or use the specify collation for the ORDER clause.
Binary collations
Binary collations sort data based on the sequence of
coded values that are defined by the locale and data type. They are
case sensitive. A binary collation in SQL Server defines the locale
and the ANSI code page that will be used. This enforces a binary sort
order. Because they are relatively simple, binary collations help
improve application performance. For non-Unicode data types, data
comparisons are based on the code points that are defined in the ANSI
code page. For Unicode data types, data comparisons are based on the
Unicode code points. For binary collations on Unicode data types, the
locale is not considered in data sorts. For example,
Latin_1_General_BIN and Japanese_BIN yield identical sorting results
when they are used on Unicode data.
There are two types of binary
collations in SQL Server; the older BIN collations and the newer BIN2
collations. In a BIN2 collation all characters are sorted according to
their code points. In a BIN collation only the first character is
sorted according to the code point, and remaining characters are
sorted according to their byte values. (Because the Intel platform is
a little endian architecture, Unicode code characters are always
stored byte-swapped.)
declare #Test table (name varchar(20) collate Latin1_General_BIN2)
insert #Test values ('Hi'), ('Toi'), ('>Toi'), ('iHh'), ('hi'), ('IhH'), ('1Hi'), ('2Hi')
select * from #Test order by name desc
Or just
select * from #Test order by name collate Latin1_General_BIN2 desc
Use ASCII Value for column and order by it in Descending order. ASCII will order your first later of word then you can apply order on your column
SELECT Name FROM #tblTest ORDER BY ASCII(Name) desc,Name
Output in Descending:
Output in Ascending:

Reading Unicode strings from SQL Server

I know strings need to be prefixed with N' in SQL Server (2012) INSERT statements to store them as UNICODE but do they have to be retrieved (SELECT statement) in a certain way as well so they are in UNICODE?
I am able to store international strings correctly with N notation but when I run SELECT query to fetch the records back, it comes as question marks. My query is very simple.
SELECT COLUMN1, COLUMN2 FROM TABLE1
I am looking at other possible reasons that may have caused this issue but at least I want to eliminate the SQL statement above. Should it read COLUMN1 and COLUMN2 columns correctly when they both store UNICODE strings using N notation? Do I have to do anything to the statement to tell it they are UNICODE?
Within management studio you should not need to do anything special to display the correct values. Make sure that the columns in your table is defined as Unicode strings NVARCHAR instead of ANSI strings VARCHAR.
The following example demonstrates the concept:
CREATE TABLE UnicodeExample
(
MyUnicodeColumn NVARCHAR(100)
,MYANSIColumn VARCHAR(100)
)
INSERT INTO UnicodeExample
(
MyUnicodeColumn
,MYANSIColumn
)
VALUES
(
N'איש'
,N'איש'
)
SELECT *
FROM UnicodeExample
DROP TABLE UnicodeExample
In the above example the column MyUnicodeColumn is defined as an NVARCHAR(100) and MYANSIColumn is defined as a VARCHAR(100). The query will correctly return the result for MyUnicodeColumn but will return ??? for MYANSIColum.

Entering special characters fails in Oracle table

I need to test if my application is reading special characters from the database and displaying them in exactly the same way. For this, I need to populate the database table with all special characters available. However, I am not sure how I can specify the special characters in the sql insert query. Can anyone please guide me to an example where I can insert a special character in the query? For simplicity sake, suppose the table is a City table with Area and Avg_Temperature being the 2 columns. If I need to insert the degree (celcius/farhenheit) symbol in Avg_Temperature column, how should I write the query?
*[Edit on 1/9/2012 at 2:50PM EST]*As per Justin Cave's suggestion below, I did following analysis:
Table: create table city(area number, avg_temperature nvarchar2(10));
Date: insert into city values (1100, '10◦C');
Query:
select dump(avg_temperature, 1010) from city where area = 1100;
O/P
DUMP(AVG_TEMPERATURE,1010)
----------------------------------------------------------
Typ=1 Len=8 CharacterSet=AL16UTF16: 0,49,0,48,0,191,0,67
Query
select value$ from sys.props$ where name='NLS_CHARACTERSET';
O/P
VALUE$
----------------
WE8MSWIN1252
Query:
select value$ from sys.props$ where name='NLS_NCHAR_CHARACTERSET';
O/P
----------------
AL16UTF16
It seems that the insert does mess up the special characters as Justin Cave suggested. But I am not able to understand why this is happening? Can anyone please provide related suggestion?
First you should not store the symbol as part of your column. That requires you to declare the column as VARCHAR which will give you lots of problems in the long run (e.g. you cannot sum() on them, you cannot avg() on them and so on)
You should store the unit in which the temperature was taken in a second column (e.g. 1 = celcius and 2 = fahrenheit) and translate this when displaying the data in the frontend. If you really want to store the symbol, declare the units columns as CHAR(1):
CREATE TABLE readings
(
area number(22),
avg_temperature number(10,3),
units varchar(2)
)
Then you can insert it as follows:
INSERT INTO readings
(area, avg_temperature, units)
VALUES
(1000, 12.3, '°C');
But again: I would not recommend to store the actual symbol. Store only the code!
First you need to know what the database character set is. Then you need to know what character set your "client" connection is using. Life is always easier if these are the same.
If your databse is utf-8 and your client is utf-8 then you don't need to do any character escaping you can just use the utf-8 encoding for the desired character.
In your example the degree character is unicode codepoint u+00b0.
In utf-8 this is a two-byte sequence: x'c2', x'b0'.