What is the difference between varchar and varchar2 in Oracle? - oracle

What is the difference between varchar and varchar2?

As for now, they are synonyms.
VARCHAR is reserved by Oracle to support distinction between NULL and empty string in future, as ANSI standard prescribes.
VARCHAR2 does not distinguish between a NULL and empty string, and never will.
If you rely on empty string and NULL being the same thing, you should use VARCHAR2.

Currently VARCHAR behaves exactly the same as VARCHAR2. However, the type VARCHAR should not be used as it is reserved for future usage.
Taken from: Difference Between CHAR, VARCHAR, VARCHAR2

Taken from the latest stable Oracle production version 12.2:
Data Types
The major difference is that VARCHAR2 is an internal data type and VARCHAR is an external data type. So we need to understand the difference between an internal and external data type...
Inside a database, values are stored in columns in tables. Internally, Oracle represents data in particular formats known as internal data types.
In general, OCI (Oracle Call Interface) applications do not work with internal data type representations of data, but with host language data types that are predefined by the language in which they are written. When data is transferred between an OCI client application and a database table, the OCI libraries convert the data between internal data types and external data types.
External types provide a convenience for the programmer by making it possible to work with host language types instead of proprietary data formats. OCI can perform a wide range of data type conversions when transferring data between an Oracle database and an OCI application. There are more OCI external data types than Oracle internal data types.
The VARCHAR2 data type is a variable-length string of characters with a maximum length of 4000 bytes. If the init.ora parameter max_string_size is default, the maximum length of a VARCHAR2 can be 4000 bytes. If the init.ora parameter max_string_size = extended, the maximum length of a VARCHAR2 can be 32767 bytes
The VARCHAR data type stores character strings of varying length. The first 2 bytes contain the length of the character string, and the remaining bytes contain the string. The specified length of the string in a bind or a define call must include the two length bytes, so the largest VARCHAR string that can be received or sent is 65533 bytes long, not 65535.
A quick test in a 12.2 database suggests that as an internal data type, Oracle still treats a VARCHAR as a pseudotype for VARCHAR2. It is NOT a SYNONYM which is an actual object type in Oracle.
SQL> select substr(banner,1,80) from v$version where rownum=1;
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> create table test (my_char varchar(20));
Table created.
SQL> desc test
Name Null? Type
MY_CHAR VARCHAR2(20)
There are also some implications of VARCHAR for ProC/C++ Precompiler options. For programmers who are interested, the link is at: Pro*C/C++ Programmer's Guide

After some experimentation (see below), I can confirm that as of September 2017, nothing has changed with regards to the functionality described in the accepted answer:-
Rextester demo for Oracle 11g:
Empty strings are inserted as NULLs for both VARCHAR
and VARCHAR2.
LiveSQL demo for Oracle 12c: Same results.
The historical reason for these two keywords is explained well in an answer to a different question.

VARCHAR can store up to 2000 bytes of characters while VARCHAR2 can store up to 4000 bytes of characters.
If we declare datatype as VARCHAR then it will occupy space for NULL values. In the case of VARCHAR2 datatype, it will not occupy any space for NULL values. e.g.,
name varchar(10)
will reserve 6 bytes of memory even if the name is 'Ravi__', whereas
name varchar2(10)
will reserve space according to the length of the input string. e.g., 4 bytes of memory for 'Ravi__'.
Here, _ represents NULL.
NOTE: varchar will reserve space for null values and varchar2 will not reserve any space for null values.

Currently, they are the same. but previously
Somewhere on the net, I read that,
VARCHAR is reserved by Oracle to support distinction between NULL and empty string in future, as ANSI standard prescribes.
VARCHAR2 does not distinguish between a NULL and empty string, and never will.
Also,
Emp_name varchar(10) - if you enter value less than 10 digits then remaining space cannot be deleted. it used total of 10 spaces.
Emp_name varchar2(10) - if you enter value less than 10 digits then remaining space is automatically deleted

Related

Are EXTENDED VARCHAR2 baned to become synchronized record fields?

My app is built on an Oracle Database.
Would it be possible to overcome the 4000 byte of Text limitation we have for Synchronized Record fields of appian?
I know the VARCHAR2(4000) limitation is considered to be a standard column type by Oracle, then choosing the EXTENDED for param. max_string_size in the DB would make it an "extended data type", as CLOB is. But since CLOB is forbidden to become a Snyc. RT field, would my large VARCHAR2 columns be also forbidden?
Asking for people who tried it. If no one did, I will ask the DBA, but could be easier to ask here ;)
My opinion is, don't bother with the extended string option. It provides no real benefit. A varchar2 greater than 4KB is a CLOB under a different name.

Unable to set precision for INTEGER data type in SQL CREATE TABLE command

I am trying to create the following table in Oracle.
CREATE TABLE CUSTOMER(CUST_ID INT(10),
CUST_NAME VARCHAR2(50),
CUST_SEX CHAR(2),
CUST_STATE VARCHAR2(50),
CUST_COUNTRY VARCHAR2(50));
I get an error saying that the right parenthesis is missing. In reality, the issue is with the INT data type for the CUST_ID column. Once I remove the precision :(10) from the DDL query, I am able to execute it successfully.
Oracle docs don't specify anything with regarding to whether this data type can be accompanied by a precision parameter or not. However Oracle does mention that INTEGER/INT is per ANSI standards.
https://docs.oracle.com/cd/B19306_01/olap.102/b14346/dml_datatypes002.htm
Certain other non-official references describe INT/INTEGER to be a synonym for NUMBER(38).
Can someone please tell me if precision cannot indeed be specified for INT datatype?
The Oracle docs state that:
SQL statements that create tables and clusters can also use ANSI data types and data types from the IBM products SQL/DS and DB2. Oracle recognizes the ANSI or IBM data type name that differs from the Oracle Database data type name. It converts the data type to the equivalent Oracle data type
As the table below that sentence states, int, integer, and (surprisingly?) smallint are all synonyms for number(38), so you cannot specify a precision for them. For your usecase, if you want an integer number with ten digits, you should use number(10).
Let me try: precision cannot indeed be specified for INT datatype.
How did it sound?
Documentation says:
<snip>
| { NUMERIC | DECIMAL | DEC } [ (precision [, scale ]) ] --> precision + scale
| { INTEGER | INT | SMALLINT } --> no precision for integers
| FLOAT [ (size) ]
<snip>
The INT[EGER] data type (which should be , at least mostly, a 4-byte binary integer), in Oracle, exists, if at all, in PL/SQL stored procedures.
Your best bet is to design a NUMBER(5) for a SMALLINT, a NUMBER(9) for an INTEGER, and a NUMBER(18) for a LARGEINT/BIGINT
If you go:
CREATE TABLE dropme (i INT);
, in Oracle, you get a table with a column i NUMBER (with no length specification, which boils down to a pretty in-efficient NUMBER(38).
The Oracle numeric data types are NUMBER , with an optional overall precision and an optional decimal scale, and FLOAT.
And an Oracle NUMBER, at least as I understood it, is a variable-length construct, with a binary, two-byte, length indicator for the whole thing, followed by a binary decimal notation , in which every following half-byte can hold between 0000 and 1001, binary, or 0 to 9 - except the last one, which contains the sign: positive/negative.
As the documentation says, INTEGER is equivalent to NUMBER(38).
You can just use INTEGER where you want to store integers of any size, or you can use NUMBER(n) if you want to constrain the number of digits in the values to n.
Note: the only reason for specifying the precision in Oracle is for validation and documentation. There is no space advantage in using smaller values of n: the value 123456 occupies the same number of bytes in NUMBER(6) and NUMBER(38) and INTEGER columns - i.e. 4 bytes.

VARCHAR2 datatype in ORACLE

I am very new to oracle and today I found about the data type VARCHAR2, and I wanted to learn more about it and google the datatype where I met the problem.
I have gone through few articles about the datatype, and I found out some direct opposite descriptions for VARCHAR2.
DESCRIPTION 1:
When you create a table with a VARCHAR2 column, you specify a maximum
column length (in bytes, not characters) between 1 and 2000 for the
VARCHAR2 column(article)
DESCRIPTION 2:
you can store up to 4000 characters in a VARCHAR2 column. (article)
As you can see it is bit confusing. Is VARCHAR2 is to specify the maximum column length or maximum characters length? Somebody please explain me which one is the correct one?
It depends on your Oracle version, but both articles are mostly incorrect.
When you DECLARE the column, you can either declare the stated length EXPLICITLY as either bytes or characters, or IMPLICITLY using your session's default.
Also, the maximum length is 4000 bytes, NOT characters. Even if you declare VARCHAR2(4000 CHAR), the column cannot store more than 4000 BYTES. It will store 4000 characters if they are all single-byte, otherwise it will store fewer than 4000 characters.
DESCRIPTION 2:
you can store up to 4000 characters in a VARCHAR2 column.
This is correct
The VARCHAR2 datatype stores variable-length character strings. When you create a table with a VARCHAR2 column, you specify a maximum string length (in bytes or characters) between 1 and 4000 bytes for the VARCHAR2 column.
=> varchar2 datatype is same as varchar datatype.
=> its datatype with variable lengh.
Ex. "name varchar2(20)" and pass the value of name is "Ram" so, LENGTH(name) is 3 NOT 20.
=> its internal datatype managed by oracle server only.
=> even if, you declare varchar oracle implicitely converts to into varchar2

Oracle extended data types in combination with char semantics

There is one aspect of the extended data types introduced with Oracle 12 that I don't quite understand. The documentation (https://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF55623) says:
A VARCHAR2 or NVARCHAR2 data type with a declared size of greater than 4000 bytes, or a RAW data type with a declared size of greater than 2000 bytes, is an extended data type. Extended data type columns are stored out-of-line, leveraging Oracle's LOB technology.
According to this definition does "VARCHAR2(4000 CHAR)" have "a declared size of greater than 4000 bytes" because with a multi-byte character set (e.g. ALS32UTF8) it could contain more that 4000 bytes?
Or more specific: What happens when I create a column of that type? I could think of the following possibilities:
It is created with an extended data type, so that the content of that column is always stored in a CLOB regardless of its size.
The values for that column are stored inline if they need not more than 4000 bytes, and as CLOB if they are longer.
It will refuse to store any values with more than 4000 bytes. To circumvent that I have to declare the column as VARCHAR2(4001 CHAR) or something similar.
Edit: The question had been marked as a duplicate of Enter large content to oracle database for a few weeks, but I don't think it is. The other question is generally about how you can enter more than 4000 characters in a VARCHAR2 column, but I am asking a very specific question about an edge case.

Difference between VARCHAR2(10 CHAR) and NVARCHAR2(10)

I've installed Oracle Database 10g Express Edition (Universal) with the default settings:
SELECT * FROM NLS_DATABASE_PARAMETERS;
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16
Given that both CHAR and NCHAR data types seem to accept multi-byte strings, what is the exact difference between these two column definitions?
VARCHAR2(10 CHAR)
NVARCHAR2(10)
The NVARCHAR2 datatype was introduced by Oracle for databases that want to use Unicode for some columns while keeping another character set for the rest of the database (which uses VARCHAR2). The NVARCHAR2 is a Unicode-only datatype.
One reason you may want to use NVARCHAR2 might be that your DB uses a non-Unicode character set and you still want to be able to store Unicode data for some columns without changing the primary character set. Another reason might be that you want to use two Unicode character set (AL32UTF8 for data that comes mostly from western Europe, AL16UTF16 for data that comes mostly from Asia for example) because different character sets won't store the same data equally efficiently.
Both columns in your example (Unicode VARCHAR2(10 CHAR) and NVARCHAR2(10)) would be able to store the same data, however the byte storage will be different. Some strings may be stored more efficiently in one or the other.
Note also that some features won't work with NVARCHAR2, see this SO question:
Oracle Text will not work with NVARCHAR2. What else might be unavailable?
I don't think answer from Vincent Malgrat is correct. When NVARCHAR2 was introduced long time ago nobody was even talking about Unicode.
Initially Oracle provided VARCHAR2 and NVARCHAR2 to support localization. Common data (include PL/SQL) was hold in VARCHAR2, most likely US7ASCII these days. Then you could apply NLS_NCHAR_CHARACTERSET individually (e.g. WE8ISO8859P1) for each of your customer in any country without touching the common part of your application.
Nowadays character set AL32UTF8 is the default which fully supports Unicode. In my opinion today there is no reason anymore to use NLS_NCHAR_CHARACTERSET, i.e. NVARCHAR2, NCHAR2, NCLOB. Note, there are more and more Oracle native functions which do not support NVARCHAR2, so you should really avoid it. Maybe the only reason is when you have to support mainly Asian characters where AL16UTF16 consumes less storage compared to AL32UTF8.
The NVARCHAR2 stores variable-length character data. When you
create a table with the NVARCHAR2 column, the maximum size is always
in character length semantics, which is also the default and only
length semantics for the NVARCHAR2 data type.
The NVARCHAR2data type uses AL16UTF16character set which encodes Unicode data in the UTF-16 encoding. The AL16UTF16 use 2 bytes to store a character. In addition, the maximum byte length of an NVARCHAR2 depends on the configured national character set.
VARCHAR2 The maximum size of VARCHAR2 can be in either bytes or characters. Its column only can store characters in the default character
set while the NVARCHAR2 can store virtually any characters. A single character may require up to 4 bytes.
By defining the field as:
VARCHAR2(10 CHAR) you tell Oracle it can use enough space to store 10
characters, no matter how many bytes it takes to store each one. A single character may require up to 4 bytes.
NVARCHAR2(10) you tell Oracle it can store 10 characters with 2 bytes per character
In Summary:
VARCHAR2(10 CHAR) can store maximum of 10 characters and maximum of 40 bytes (depends on the configured national character set).
NVARCHAR2(10) can store maximum of 10 characters and maximum of 20 bytes (depends on the configured national character set).
Note: Character set can be UTF-8, UTF-16,....
Please have a look at this tutorial for more detail.
Have a good day!
nVarchar2 is a Unicode-only storage.
Though both data types are variable length String datatypes, you can notice the difference in how they store values.
Each character is stored in bytes. As we know, not all languages have alphabets with same length, eg, English alphabet needs 1 byte per character, however, languages like Japanese or Chinese need more than 1 byte for storing a character.
When you specify varchar2(10), you are telling the DB that only 10 bytes of data will be stored. But, when you say nVarchar2(10), it means 10 characters will be stored. In this case, you don't have to worry about the number of bytes each character takes.

Resources