Difference in char datatype in SQL - sql

Is their any difference between char(1) and char(1 byte) in Oracle?
Example:
create table aaa(flag char(1));
and
create table aaa(flag char(1 byte));
In the first example Explicitly i did not mentioned byte or character. Hence the default value will be BYTE or CHARACTER?

It will depend on the setting of NLS_LENGTH_SEMANTICS. As per the documentation, this defaults to BYTE.
Depending on this setting, there is a major difference between
CHAR(1 CHAR)
and
CHAR(1 BYTE)
The former will allow storage of 1 character, including those which require more than one byte to encode, whereas the latter only allows for 1 byte of storage and will not be able to store characters which require 2 or more bytes to encode.
As a result, it is always a good idea to explicitly qualify the size of *CHAR fields explicitly with either BYTE or CHAR
The following shows how the storage differs.
CREATE TABLE SomeTable
(
Char1 CHAR(1 CHAR),
Char2 CHAR(1 BYTE)
);
INSERT INTO SomeTable(Char1, Char2) VALUES('A', 'A');
INSERT INTO SomeTable(Char1, Char2) VALUES('Й', 'Й'); -- Insert into Char2 fails

Related

SQL Query to count entire duplicate row

I am looking for help with a query to do the following:
Before the insert of a row, find how many rows in 2 tables have the same information as is being inserted.
So basically I am looking to see if this row will be a complete duplicate.
I want to base this on all the columns, not just the PK, because if there is even one column different then this is a valid insert.
This is something along the lines of what I need, although incorrect:
SELECT COUNT(*)
FROM ORDER_TRF_HEADER
WHERE
((SELECT * FROM ORDER_TRF_HEADER_COMPLETE WHERE MA_PONUM = '29608207') = (SELECT * FROM ORDER_TRF_HEADER WHERE MA_PONUM = '29608207'));
Table - ORDER_TRF_HEADER
MA_CUST VARCHAR2(8 BYTE)
MA_PONUM VARCHAR2(30 BYTE)
MA_ODATE VARCHAR2(8 BYTE)
MA_ITEMS NUMBER(3,0)
MA_SALEM VARCHAR2(2 BYTE)
MA_PDAYS NUMBER(3,0)
MA_CURR VARCHAR2(3 BYTE)
Table - ORDER_TRF_HEADER_COMPLETE
MA_CUST VARCHAR2(8 BYTE)
MA_PONUM VARCHAR2(30 BYTE)
MA_ODATE VARCHAR2(8 BYTE)
MA_ITEMS NUMBER(3,0)
MA_SALEM VARCHAR2(2 BYTE)
MA_PDAYS NUMBER(3,0)
MA_CURR VARCHAR2(3 BYTE)
Thanks
I want to base this on all the columns, not just the PK, because if there is even one column different then this is a valid insert.
then your issue is that you have NOT defined your primary key correctly.
Certainly there are good reasons for not maintaining a primary key consisting of every attribute in the record, however a better solution than checking for duplicates in such a clumsy way before inserting would be to maintain a has of the data as a unique key.
You can try INTERSECT.
SELECT COUNT(*)
FROM (SELECT *
FROM order_trf_header_complete
WHERE ma_ponum = '29608207'
INTERSECT
SELECT *
FROM order_trf_header
WHERE ma_ponum = '29608207') ;
Note:: You better use all column names explicitly instead of select *

How do I fix SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated

Gives me error when I try to insert and it finally inserts after couple of retries with out any error.
SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated.
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
INSERT statement:
INSERT INTO up_module_master
(
mr_id,
mr_name,
mr_desc,
mr_parent,
created_by,
created_date,
modified_date,
module_type,
module_link,
link_text,
help_text shortcut_link,
shortcut_name,
shortcut_flag,
module_display_name
)
SELECT max(u1.mr_id)+1,
'Notification Engine',
'Notification Engine Module',
0,1,
SYSDATE,
'',
'',
'../../jalsweb/Logout.jsp',
'HTTP',
'',
'',
'',
0,
'Notification Engine'
FROM up_module_master u1;
Below is the table definition:
CREATE TABLE "up_module_master"
(
"mr_id" NUMBER (10, 0) NOT NULL ENABLE,
"mr_name" VARCHAR2 (200 byte) NOT NULL ENABLE,
"mr_desc" VARCHAR2 (250 byte),
"mr_parent" NUMBER,
"created_by" NUMBER,
"created_date" TIMESTAMP (6),
"modified_date" TIMESTAMP (6),
"module_type" VARCHAR2 (100 byte),
"module_link" VARCHAR2 (200 byte),
"link_text" VARCHAR2 (250 byte),
"help_text" VARCHAR2 (250 byte),
"shortcut_link" VARCHAR2 (400 byte),
"shortcut_name" VARCHAR2 (100 byte),
"shortcut_flag" NUMBER,
"module_display_name" VARCHAR2 (100 byte),
"audit_type" VARCHAR2 (100 byte),
"service_id" NUMBER,
"module_regis_type" NUMBER DEFAULT 1,
CONSTRAINT "PK_UP_MODULE_MASTER" PRIMARY KEY ("mr_id"),
CONSTRAINT "UP_MODULE_MASTER_UP_MODUL_FK1" FOREIGN KEY ("mr_parent")
REFERENCES "up_module_master" ("mr_id") ENABLE
)
Looks like MR_ID is not an identity seed. If another process is attempting to insert a record at the same time as you, both will try to insert the same ID and you will get this error. I suggest that you change the column to be auto incrementing. You will need to create a sequence and then a trigger if using pre version 12 or the identity column if using later versions:
Oracle: how to create an identity column?
The link above has all the details for doing this.
the problem is, that someone other inserted and commited a row with the same key meanwhile
consider using a sequence (it looks like the sequence is already defined):
SELECT seq_name.nextval, ... FROM dual
The reason why it's failing is because "select max(mr_id) + 1 ..." is going to be a fixed number for all rows that you're selecting - it's not going to increment for each row in your select statement. (Duh! See comments below!)
As others have said, use a sequence! (Yes, there are other ways you could use to get unique values as part of your select statement, but they'd be the wrong thing to use. Sequences FTW!)

Oracle VARCHAR (15 BYTE) to MS SQL Server 2014 DATA TYPES

I am creating multiple tables in MS SQL SERVER 2014 to that will receive data from an Oracle server. Some of the data types that are coming over from Oracle are set to VARCHAR2 (15 BYTE), VARCHAR2(60 BYTE) ETC....
I need to know what I should set my data types too in the MS SQL SERVER tables.
ITEM_NO VARCHAR(15 BYTE)
UNIT_OF_MEASURE CHAR(2 BYTE)
PARTNER_SKU VARCHAR(15 BYTE)
UPC CHAR(12 BYTE)
ITEM_DESC VARCHAR(60 BYTE)
ALT_ITEM_NO VARCHAR(15 BYTE)
As previously stated in the comments above by #Gordon Linoff and #user2067753 in SQL Server you do not need to define the word BYTE when specifying data types in SQL Server. So for your declared fields above:
ITEM_NO VARCHAR(15)
UNIT_OF_MEASURE CHAR(2)
PARTNER_SKU VARCHAR(15)
UPC CHAR(12)
ITEM_DESC VARCHAR(60)
ALT_ITEM_NO VARCHAR(15)
MSDN has many articles which you might also find helpful:
Data Types
Creating Tables
You also might find these documents quite useful as it compares both Microsoft SQL Server to Oracle and documents a load of the differences:
From Oracle
On MSDN
Byte in Oracle is optional, Just used to enforce the size to be specific number of bytes rather than the length of the varchar value. There is no equivalent in SQL Server

ALTER statement: Why VARCHAR2(50 BYTE) instead of VARCHAR2(50 CHAR)? [duplicate]

This question already has answers here:
varchar2(n BYTE|CHAR) default -> CHAR or BYTE
(2 answers)
Closed 9 years ago.
I executed the following (Oracle 11g) SQL statement to increase an existing column's length from VARCHAR2(20 CHAR) to VARCHAR2(50 CHAR):
ALTER TABLE USERX.MY_TABLE MODIFY (LASTNAME VARCHAR2(50));
It succeeded without incident, but when I look at the new Data Type column, I see: VARCHAR2(50 BYTE) instead of VARCHAR2(50 CHAR).
My questions are:
Why BYTE and not CHAR? What have I done incorrectly?
How do I fix the column's length to be VARCHAR2(100 CHAR)?
Answering myself (thanks to the tip provided by this other answer):
I should have executed instead:
ALTER TABLE USERX.MY_TABLE MODIFY (LASTNAME VARCHAR2(50 CHAR));
(note the extra CHAR after 50)

auto_increment with varchar in oracle

i have this table
CREATE TABLE WishList(
idWishList VARCHAR2(40 BYTE) ,
WishListName VARCHAR2(40 CHAR) NOT NULL,
id_User VARCHAR2(40 BYTE) NOT NULL
)
now how can i use auto_increment with varchar in oracle ??
You can add a trigger:
create or replace trigger some_trig_name
before insert on WishList
for each row
begin
:new.idWishList := to_char(your_sequence.nextval);
end some_trig_name;
In the example I used a seq but you can put whatever you want
As I remember, Oracle doesn't have an auto_increment functionality. It has sequences and developers should add special function like getNextId() and use it in insert statements like
insert into table (id,...) values(getNextId() ,..)
So, you can implement you own function which returns new id for your field with your own algorithm.