Professional Documents
Culture Documents
The JOIN keyword is used in an SQL statement to query data from two or more tables, based on a relationship between certain columns in these tables. Tables in a database are often related to each other with keys. A primary key is a column (or a combination of columns) with a unique value for each row. Each primary key value must be unique within the table. The purpose is to bind data together, across tables, without repeating all of the data in every table. Look at the "Persons" table: P_Id 1 2 3 LastName Hansen Svendson Pettersen FirstName Ola Tove Kari Address Timoteivn 10 Borgvn 23 Storgt 20 City Sandnes Sandnes Stavanger
Note that the "P_Id" column is the primary key in the "Persons" table. This means that no two rows can have the same P_Id. The P_Id distinguishes two persons even if they have the same name. Next, we have the "Orders" table: O_Id 1 2 3 4 5 OrderNo 77895 44678 22456 24562 34764 P_Id 3 3 1 1 15
Note that the "O_Id" column is the primary key in the "Orders" table and that the "P_Id" column refers to the persons in the "Persons" table without using their names. Notice that the relationship between the two tables above is the "P_Id" column.
JOIN: Return rows when there is at least one match in both tables LEFT JOIN: Return all rows from the left table, even if there are no matches in the right table RIGHT JOIN: Return all rows from the right table, even if there are no matches in the left table FULL JOIN: Return rows when there is a match in one of the tables
The "Orders" table: O_Id 1 2 3 4 5 OrderNo 77895 44678 22456 24562 34764 P_Id 3 3 1 1 15
Now we want to list all the persons with any orders. We use the following SELECT statement:
The result-set will look like this: LastName Hansen Hansen Pettersen Pettersen FirstName Ola Ola Kari Kari OrderNo 22456 24562 77895 44678
The INNER JOIN keyword return rows when there is at least one match in both tables. If there are rows in "Persons" that do not have matches in "Orders", those rows will NOT be listed.
Pettersen
Kari
Storgt 20
Stavanger
The "Orders" table: O_Id 1 2 3 4 5 OrderNo 77895 44678 22456 24562 34764 P_Id 3 3 1 1 15
Now we want to list all the persons and their orders - if any, from the tables above. We use the following SELECT statement:
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons LEFT JOIN Orders ON Persons.P_Id=Orders.P_Id ORDER BY Persons.LastName
The result-set will look like this: LastName Hansen Hansen Pettersen Pettersen Svendson FirstName Ola Ola Kari Kari Tove OrderNo 22456 24562 77895 44678
The LEFT JOIN keyword returns all the rows from the left table (Persons), even if there are no matches in the right table (Orders).
The "Orders" table: O_Id 1 2 3 4 5 OrderNo 77895 44678 22456 24562 34764 P_Id 3 3 1 1 15
Now we want to list all the orders with containing persons - if any, from the tables above. We use the following SELECT statement:
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons RIGHT JOIN Orders ON Persons.P_Id=Orders.P_Id
ORDER BY Persons.LastName
The result-set will look like this: LastName Hansen Hansen Pettersen Pettersen FirstName Ola Ola Kari Kari OrderNo 22456 24562 77895 44678 34764
The RIGHT JOIN keyword returns all the rows from the right table (Orders), even if there are no matches in the left table (Persons).
O_Id 1 2 3 4 5
P_Id 3 3 1 1 15
Now we want to list all the persons and their orders, and all the orders with their persons. We use the following SELECT statement:
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons FULL JOIN Orders ON Persons.P_Id=Orders.P_Id ORDER BY Persons.LastName
The result-set will look like this: LastName Hansen Hansen Pettersen Pettersen Svendson FirstName Ola Ola Kari Kari Tove 34764 OrderNo 22456 24562 77895 44678
The FULL JOIN keyword returns all the rows from the left table (Persons), and all the rows from the right table (Orders). If there are rows in "Persons" that do not have matches in "Orders", or if there are rows in "Orders" that do not have matches in "Persons", those rows will be listed as well
Now we want to select only the persons living in the city "Sandnes" from the table above. We use the following SELECT statement:
The result-set will look like this: P_Id 1 2 LastName Hansen Svendson FirstName Ola Tove Address Timoteivn 10 Borgvn 23 City Sandnes Sandnes
This is correct: SELECT * FROM Persons WHERE FirstName='Tove' This is wrong: SELECT * FROM Persons WHERE FirstName=Tove
This is correct: SELECT * FROM Persons WHERE Year=1965 This is wrong: SELECT * FROM Persons WHERE Year='1965'
BETWEEN LIKE IN
Between an inclusive range Search for a pattern If you know the exact value you want to return for at least one of the columns
ORDER BY Example
The "Persons" table: P_Id 1 2 3 4 LastName Hansen Svendson Pettersen Nilsen FirstName Ola Tove Kari Tom Address Timoteivn 10 Borgvn 23 Storgt 20 Vingvn 23 City Sandnes Sandnes Stavanger Stavanger
Now we want to select all the persons from the table above, however, we want to sort the persons by their last name.
The result-set will look like this: P_Id 1 4 3 2 LastName Hansen Nilsen Pettersen Svendson FirstName Ola Tom Kari Tove Address Timoteivn 10 Vingvn 23 Storgt 20 Borgvn 23 City Sandnes Stavanger Stavanger Sandnes
The result-set will look like this: P_Id 2 3 4 1 LastName Svendson Pettersen Nilsen Hansen FirstName Tove Kari Tom Ola Address Borgvn 23 Storgt 20 Vingvn 23 Timoteivn 10 City Sandnes Stavanger Stavanger Sandnes
The second form specifies both the column names and the values to be inserted:
INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)
Now we want to insert a new row in the "Persons" table. We use the following SQL statement:
The "Persons" table will now look like this: P_Id 1 2 3 4 LastName Hansen Svendson Pettersen Nilsen FirstName Ola Tove Kari Johan Address Timoteivn 10 Borgvn 23 Storgt 20 Bakken 2 City Sandnes Sandnes Stavanger Stavanger
INSERT INTO Persons (P_Id, LastName, FirstName) VALUES (5, 'Tjessem', 'Jakob')
The "Persons" table will now look like this: P_Id 1 2 3 4 5 LastName Hansen Svendson Pettersen Nilsen Tjessem FirstName Ola Tove Kari Johan Jakob Address Timoteivn 10 Borgvn 23 Storgt 20 Bakken 2 City Sandnes Sandnes Stavanger Stavanger
Note: Notice the WHERE clause in the UPDATE syntax. The WHERE clause specifies which record or records that should be updated. If you omit the WHERE clause, all records will be updated!
Now we want to update the person "Tjessem, Jakob" in the "Persons" table. We use the following SQL statement:
UPDATE Persons SET Address='Nissestien 67', City='Sandnes' WHERE LastName='Tjessem' AND FirstName='Jakob'
The "Persons" table will now look like this: P_Id 1 2 3 4 5 LastName Hansen Svendson Pettersen Nilsen Tjessem FirstName Ola Tove Kari Johan Jakob Address Timoteivn 10 Borgvn 23 Storgt 20 Bakken 2 Nissestien 67 City Sandnes Sandnes Stavanger Stavanger Sandnes
The "Persons" table would have looked like this: P_Id 1 2 3 4 5 LastName Hansen Svendson Pettersen Nilsen Tjessem FirstName Ola Tove Kari Johan Jakob Address Nissestien 67 Nissestien 67 Nissestien 67 Nissestien 67 Nissestien 67 City Sandnes Sandnes Sandnes Sandnes Sandnes
The HAVING clause was added to SQL because the WHERE keyword could not be used with aggregate functions.
Now we want to find if any of the customers have a total order of less than 2000. We use the following SQL statement:
The result-set will look like this: Customer Nilsen SUM(OrderPrice) 1700
Now we want to find if the customers "Hansen" or "Jensen" have a total order of more than 1500.
SELECT Customer,SUM(OrderPrice) FROM Orders WHERE Customer='Hansen' OR Customer='Jensen' GROUP BY Customer HAVING SUM(OrderPrice)>1500
The result-set will look like this: Customer Hansen Jensen SUM(OrderPrice) 2000 2000
2 3 4 5 6
Now we want to find the total sum (total order) of each customer. We will have to use the GROUP BY statement to group the customers. We use the following SQL statement:
The result-set will look like this: Customer Hansen Nilsen Jensen SUM(OrderPrice) 2000 1700 2000
Nice! Isn't it? :) Let's see what happens if we omit the GROUP BY statement:
The result-set will look like this: Customer Hansen Nilsen Hansen SUM(OrderPrice) 5700 5700 5700
The result-set above is not what we wanted. Explanation of why the above SELECT statement cannot be used: The SELECT statement above has two columns specified (Customer and SUM(OrderPrice). The "SUM(OrderPrice)" returns a single value (that is the total sum of the "OrderPrice" column), while "Customer" returns 6 values (one value for each row in the "Orders" table). This will therefore not give us the correct result. However, you have seen that the GROUP BY statement solves this problem.
The LIKE operator is used in a WHERE clause to search for a specified pattern in a column.
The "Persons" table: P_Id 1 2 3 LastName Hansen Svendson Pettersen FirstName Ola Tove Kari Address Timoteivn 10 Borgvn 23 Storgt 20 City Sandnes Sandnes Stavanger
Now we want to select the persons living in a city that starts with "s" from the table above. We use the following SELECT statement:
The "%" sign can be used to define wildcards (missing letters in the pattern) both before and after the pattern. The result-set will look like this: P_Id 1 2 3 LastName Hansen Svendson Pettersen FirstName Ola Tove Kari Address Timoteivn 10 Borgvn 23 Storgt 20 City Sandnes Sandnes Stavanger
Next, we want to select the persons living in a city that ends with an "s" from the "Persons" table. We use the following SELECT statement:
The result-set will look like this: P_Id 1 2 LastName Hansen Svendson FirstName Ola Tove Address Timoteivn 10 Borgvn 23 City Sandnes Sandnes
Next, we want to select the persons living in a city that contains the pattern "tav" from the "Persons" table. We use the following SELECT statement:
The result-set will look like this: P_Id 3 LastName Pettersen FirstName Kari Address Storgt 20 City Stavanger
It is also possible to select the persons living in a city that NOT contains the pattern "tav" from the "Persons" table, by using the NOT keyword. We use the following SELECT statement:
The result-set will look like this: P_Id 1 2 LastName Hansen Svendson FirstName Ola Tove Address Timoteivn 10 Borgvn 23 City Sandnes Sandnes
Note: The UNION operator selects only distinct values by default. To allow duplicate values, use UNION ALL.
PS: The column names in the result-set of a UNION are always equal to the column names in the first SELECT statement in the UNION.
"Employees_USA": E_ID 01 02 03 04 E_Name Turner, Sally Kent, Clark Svendson, Stephen Scott, Stephen
Now we want to list all the different employees in Norway and USA. We use the following SELECT statement:
The result-set will look like this: E_Name Hansen, Ola Svendson, Tove Svendson, Stephen Pettersen, Kari Turner, Sally Kent, Clark Scott, Stephen
Note: This command cannot be used to list all employees in Norway and USA. In the example above we have two employees with equal names, and only one of them will be listed. The UNION command selects only distinct values.
SELECT E_Name FROM Employees_Norway UNION ALL SELECT E_Name FROM Employees_USA
Svendson, Tove Svendson, Stephen Pettersen, Kari Turner, Sally Kent, Clark Svendson, Stephen Scott, Stephen
SQL Constraints
Constraints are used to limit the type of data that can go into a table. Constraints can be specified when a table is created (with the CREATE TABLE statement) or after the table is created (with the ALTER TABLE statement). We will focus on the following constraints:
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) )
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), UNIQUE (P_Id) )
CREATE TABLE Persons ( P_Id int NOT NULL UNIQUE, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) )
To allow naming of a UNIQUE constraint, and for defining a UNIQUE constraint on multiple columns, use the following SQL syntax:
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName) )
To allow naming of a UNIQUE constraint, and for defining a UNIQUE constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), PRIMARY KEY (P_Id) )
CREATE TABLE Persons ( P_Id int NOT NULL PRIMARY KEY, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255)
To allow naming of a PRIMARY KEY constraint, and for defining a PRIMARY KEY constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName) )
Note: In the example above there is only ONE PRIMARY KEY (pk_PersonID). However, the value of the pk_PersonID is made up of two columns (P_Id and LastName).
To allow naming of a PRIMARY KEY constraint, and for defining a PRIMARY KEY constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
Note: If you use the ALTER TABLE statement to add a primary key, the primary key column(s) must already have been declared to not contain NULL values (when the table was first created).
The "Orders" table: O_Id 1 2 3 4 OrderNo 77895 44678 22456 24562 P_Id 3 3 2 1
Note that the "P_Id" column in the "Orders" table points to the "P_Id" column in the "Persons" table. The "P_Id" column in the "Persons" table is the PRIMARY KEY in the "Persons" table. The "P_Id" column in the "Orders" table is a FOREIGN KEY in the "Orders" table. The FOREIGN KEY constraint is used to prevent actions that would destroy links between tables. The FOREIGN KEY constraint also prevents that invalid data form being inserted into the foreign key column, because it has to be one of the values contained in the table it points to.
CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, PRIMARY KEY (O_Id), FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) )
CREATE TABLE Orders ( O_Id int NOT NULL PRIMARY KEY, OrderNo int NOT NULL, P_Id int FOREIGN KEY REFERENCES Persons(P_Id) )
To allow naming of a FOREIGN KEY constraint, and for defining a FOREIGN KEY constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int,
PRIMARY KEY (O_Id), CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) )
To allow naming of a FOREIGN KEY constraint, and for defining a FOREIGN KEY constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Orders ADD CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CHECK (P_Id>0) )
CREATE TABLE Persons ( P_Id int NOT NULL CHECK (P_Id>0), LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255)
To allow naming of a CHECK constraint, and for defining a CHECK constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes') )
To allow naming of a CHECK constraint, and for defining a CHECK constraint on multiple columns, use the following SQL syntax: MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons ADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) DEFAULT 'Sandnes' )
The DEFAULT constraint can also be used to insert system values, by using functions like GETDATE():
CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, OrderDate date DEFAULT GETDATE() )
To create a DEFAULT constraint on the "City" column when the table is already created, use the following SQL: MySQL:
CHAR
CHAR should be used for storing fix length character strings. String values will be space/blank padded before stored on disk. If this type is used to store varibale length strings, it will waste a lot of disk space.
Table created.
1 row created.
COL1
VARCHAR
Currently VARCHAR behaves exactly the same as VARCHAR2. However, this type should not be used as it is reserved for future usage.
Table created.
1 row created.
COL1
VARCHAR2
VARCHAR2 is used to store variable length character strings. The string value's length will be stored on disk with the value itself.
Table created.
1 row created.
COL1
1. VARCHAR is going to be replaced by VARCHAR2 in next version. So, Oracle suggests the use VARCHAR2 instead of VARCHAR while declaring datatype. 2. VARCHAR can store up to 2000 bytes of characters while VARCHAR2 can store up to 4000 bytes of characters. 3. If we declare datatype as VARCHAR then it will occupy space for NULL values, In case of VARCHAR2 datatype it will not occupy any space.
VARCHAR is used to store variable length character strings up to 4000 characters. But, remember CHAR is faster than VARCHAR - some times up to 50% faster.
1. VARCHAR is NOT going to be replaced by VARCHAR2 in the next version. It is reserved for redefinition in some future version, probably well beyond 11g, if ever. This warning has been around since the two types were first introduced in Oracle 6 around 1989. It is there to allow Oracle some flexibility should the need arise. 2. The two types are currently synonymous, and so the storage limitations are identical. 3. As for #2, there is no difference between VARCHAR and VARCHAR2 in handling of NULL values because they are currently the same type. While I'm at it, VARCHAR2 does NOT contain an additional length indicator (as the DUMP output clearly shows), CHAR is NOT faster than VARCHAR2, and VARCHAR does NOT use space any differently to VARCHAR2 and never has done. There is no good reason to use CHAR for anything, even fixed-length keys, and there never has been. I've never seen so much complete rubbish on one page in my life.
[i]. CHAR(5) is fixed length, right padded with spaces. VARCHAR(5) is fixed length, right padded with null VARCHAR2(5) is variable length. Thus the difference between VARCHAR and VARCHAR2 is that VARCHAR is ANSI standard but takes up space whereas VARCHAR2 is Oracle-only but makes more efficient use of space. But as someone has already pointed out, Oracle have resolved this (in 9.2, maybe earlier) by casting VARCHAR to VARCHAR2. [ii]. Varchar and Varchar2 both are of variable character. Varchar can have MAximum 2000 character while Varchar can contain maximum 4000 character. [iii] Varchar is of ANSI SQL standart while Varchar2 is of Oracle standard.
Varchar vs Char
Submitted by Princevel Pereira (not verified) on Thu, 2006-12-07 01:35.
Searching is faster in CHAR as all the strings are stored at a specified position from the each other, the system doesnot have to search for the end of string. Whereas in VARCHAR the system has to first find the end of string and then go for searching.
VARCHAR was previosuly of fixed length and right padded with NULL spaces to fill up the total space. However, it seems that Oracle has resolved this issue and has made VARCHAR the same as VARCHAR2. Now, only CHAR is able of fixed length storage. VARCHAR2 is variable length - according to the values that will be stored in the database. Thanks Adilz
Varchar and varchar2 are synonyms (now at least) varchar is supposed to be removed from oracle sql, but that will probably never happen. They both use 0 to N characters up on the disk. Depending on your NLS_CHARACTER_FORMAT (its called something like that) each character can take more than one byte on disk. ASCII uses one byte per character. UTF8 I think uses one byte unless the first bit is 1 then it may add another byte (and keep doing so until the first bit of the new byte is not 1) Most other forms of unicode default to two bytes. They can all grow I believe char() should be thought of as fixd length. It will always take up the same amount of space no matter what is really stored in the column. It is a good idea to use them on fixed length things like MD5 signatures. Varchars should fragment the datafile if their contents change. If they don't fragment the datafile then Oracle is taking extra steps to prevent this. So IF you are working with a string that will always be the same length (and that is less than 255) the go with char(). Where your string is < 4000 use Varchar2. Anything else go with CLOB.
I don't feel compelled to comment on varchar. Never used it in Oracle and probably never will. However I am compelled to comment about char and varchar because of some unhelpful comments here. First of all it is easy enough to verify stuff in Oracle so it comes as a surprise at some of the comments here. char and varchar properties and length restrictions are widely available, however what is not available widely is perhaps the performance issue. I decided to put it to rest by creating a table of a million rows with essentially two columns (c char(6), vc varchar2(10)) and filled each with same values of 6 characters long (comparing 'apples' to 'apples') from a random table in my app. I issued a search: select count(*) from mytable where c = 'values' and alternatively vc = 'values' Invariably the char (c) search performed almost half as fast as the varchar2 (vc) search. Varchar2 performed much better. Don't take my word for it, try it for yourself.