Oracle10g SQL,
Chapter 8
The command to create new rows in a table is the Insert statement. The values in an insert statement must be enclosed in single quotes (?) if they are a CHAR, VARCHAR, VARCHAR2 data-type. If they are NUMERIC data-type, they do not need to be enclosed in quotes. For example even though zip_code contains only number, because it is declared as a CHAR type, it must be enclosed in single quotes.
Syntax:
INSERT INTO <table-name> [(col1, col2, col3, ?,
colN)]
VALUES (value1, value2,
value3, ?, valueN);
The part that is between brackets "[(col1, col2, col3, ?, colN)]" is optional, but it is highly recommended that you include this part because without out the column names, the values will simply be put into the table first value to first column, second value to second column and so forth. If you include the name of the columns, the insert statement will match the first value to first column you specify, the second value to the second column you specify, and so forth. This is particularly important, because at the time of writing the SQL statement, the rows and columns may match up properly without specifying the columns, but what very often happens is the DBA will add to a table. When this happens if you didn?t specify the columns your program will "Crash and Burn" unless you go to every INSERT statement in your program that is affected and make the necessary change. Given the size of many programs, this could be quite an undertaking. If you do specify the columns your program will continue to work without modifications. For this reason most companies will require you to include the column name in your INSERT statements. For this class they are also required, ANY submission of an INSERT statement without the column-names being specified will be returned to you as Unacceptable.
Examples:
1) Column-names NOT specified.
INSERT INTO customers VALUES (6, 'Jones', 'Mary', '01-JAN-1980', '555-1212');
2) Column-names specified.
INSERT INTO customers (customer_id, last_name, first_name, dob, phone)
VALUES (6, 'Jones', 'Mary', '01-JAN-1980', '555-1212');
Now let's assume the DBA (database administrator) is instructed to add a column after first for the middle initial. Our table now looks like this.
customers (customer_id, last_name, first_name, mid_init, dob, phone)
In this case the first SQL-Statement (Column-names NOT specified) will fail, because the insert statement will try to put '01-JAN-1980' into mid_init, city into address, state into city, zip_code into state (This will fail because zip is mid_init is CHAR(1) and the value is more than one character). Next you will attempt to put an invalid date value '555-1212' into dob.
However the Second SQL-Statement (Column-names specified) will still work, because we specified which values go into which columns.
Inserting NULL:
Because we only defined customer_id, last, and first as NOT NULL columns, those three columns are the only three for which we must specify values.
Example:
INSERT INTO customers (customer_id, last_name,
first_name)
VALUES (7, 'Martin',
'Elyse');
The above is fine, because the other columns where not specified as NOT NULL, so no value is required for them.
Syntax:
FROM TableName2
WHERE <conditional
expression>;
Notes: Map
your columns correctly!! Also,
you could insert into a table based on a select statement involving more
than one table.
INSERT INTO customers
(customer_id, first_name, last_name)
SELECT 10, first_name, last_name FROM customers
WHERE customer_id=1;
Updating Data in a table (The SQL-UPDATE command):
The command in SQL for updating a table is the UPDATE command.
Syntax:
UPDATE table-name
SET column1 = value1[, column2 = value2[, columnN =
valueN]]
[WHERE <logical condition> [AND|OR
<logical-condintion]]
Example:
UPDATE customers
SET phone = '555-1234';
Will change everyone's phone number to '555-1212', probably not what we wanted to do.
UPDATE customers
SET phone = '555-1234'
WHERE
customer_id = 2;
Will only change the phone number for customer 2.
Syntax:
UPDATE table_name
WHERE ...
Notes: The select clause is
being used to assign a value to a column:
Your sub-select must be enclosed in parentheses.
Make sure that your nested query returns only one value!!
EMPLOYEE_ID LAST_NAME SALARY
----------- ---------- ----------
1 Smith 800000
2 Johnson 600000
3 Hobbs 150000
4 Jones 500000
EMPLOYEE_ID LAST_NAME SALARY
----------- ---------- ----------
1 Smith 800000
2 Johnson 800000
3 Hobbs 150000
4 Jones 500000
UPDATE customers
SET (city, state) = (SELECT city, state FROM zipcode z
WHERE z.zip = customers.zip_code)
THE RETURNING CLAUSE:
The returning clause can be used to return any data from the table just updated, but just for one row of data. In 10g this can include Aggregate functions.
SQL> VAR v_dob VARCHAR2(20);
SQL> UPDATE
customers SET phone = '555-1212' WHERE customer_id=2 RETURNING dob INTO :v_dob;
1 row updated.
SQL> PRINT :v_dob;
V_DOB
--------------------------------
05-FEB-68
Deleting rows of data (The SQL-DELETE command):
The command to delete rows of data from a table is the DELETE command.
Syntax:
DELETE FROM table-name
[WHERE <logical condition> [AND|OR
<logical-condintion]]
Example:
DELETE FROM customers
WHERE customer_id = 2;
DELETE FROM customers
*
ERROR at line 1:
ORA-02292: integrity constraint (SYSTEM.SYS_C004050) violated - child record
found
-- Our good old integrity constraint at work: In this case it is the foreign key constraint to the purchases table.
DELETE FROM customers;
This will remove ALL rows from the customers table, usually not a desired result, so most DELETE commands will usually have a WHERE clause.
TRUNCATE TABLE <table-name>: This is commond to remove all rows from a table. It is much more effecient than DELETE FROM table. It is actually considered a DDL command instead of a DML command.
TRUNCATE TABLE customers2;
DEFAULT VALUES:
ALTER TABLE employees ADD (start_date DATE DEFAULT SYSDATE NOT NULL);
SQL> INSERT INTO employees (employee_id, first_name, last_name) VALUES (5, 'Howard', 'Stern');
1 row created.
SQL> select employee_id, first_name, last_name, start_date from employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME START_DAT
----------- ---------- ---------- ---------
1 James Smith 19-FEB-07
2 Ron Johnson 19-FEB-07
3 Fred Hobbs 19-FEB-07
4 Susan Jones 19-FEB-07
5 Howard Stern 19-FEB-07
MERGE INTO products p USING product_changes pc ON (p.product_id =
pc.product_id)
WHEN MATCHED THEN
UPDATE
SET p.product_type_id =
pc.product_type_id,
p.name = pc.name,
p.description = pc.description,
p.price = pc.price
WHEN NOT MATCHED THEN
INSERT (p.product_id, p.product_type_id, p.name,
p.description, p.price)
VALUES (pc.product_id, pc.product_type_id, pc.name,
pc.description, pc.price);
Many times a change to the
database requires several SQL-Statements, for example transferring money from a
savings account to a checking account, requires an UPDATE to the savings account
to decrement, and UPDATE to the checking account to increment it, and an INSERT
INTO a journal. This is called a transaction. If any of the SQL-Statements fail, the
database may wind up with incorrect data.
For example if the UPDATE to the savings account succeeds, but the UPDATE
to the checking account does not, then your out $500, or whatever the amount
is. To protect against this problem most databases support transaction processing, this works
by holding the SQL-Statements in a buffer area, until a COMMIT statement is issued. A commit statement simply tells
the database that it is ok to write the buffer items to disk. If an error occurs you can undo the
entire transaction with the ROLLBACK command.
A transaction
is:
�
Logical
Unit of Work.
�
May
Consist of Many SQL Statements.
�
Commits
and Rollbacks.
�
Savepoints.
�
Can be
used to provide data consistency.
ACID Transaction Properties (Atomicity, Consistency, Isolation, Durability):
Transaction Isolation Levels (Phantom Reads, Non-repeatable Reads, Dirty Reads):
READ UNCOMMITTED (Not supported by Oracle): Phantom Reads, Non-repeatable Reads, Dirty Reads are all allowed
READ COMMITTED (Oracle Default): Phantom Reads and Non-repeatable Reads allowed, but Dirty Reads not allowed.
REPEATABLE READS (Not supported by Oracle): Phantom Reads permitted, but Dirty Reads and Non-repeatable Reads are not allowed.
SERIALIZABLE (Most Restrictive and usually not necessary): Phantom Reads, Non-repeatable Reads, Dirty Reads are NOT allowed.
SET
TRANSACTION:
Indicates
the beginning of a transaction and sets key features.
SET TRANSACTION;
SET TRANSACTION READONLY;
-- Transaction Level
consistency
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Statement Level
consistency
SET TRANSACTION ISOLATION LEVEL COMMITTED;
COMMIT: Ends current transaction by saving
database changes and starts new transaction.
ROLLBACK: Ends current transaction by discarding
database changes.
ROLLBACK;
ROLLBACK TO SAVEPOINT <save-point-name>;
SAVEPOINT: Defines
"midpoint" for the transaction to allow
partial rollbacks.
SAVEPOINT <save-point-name>;
Example(s):
SET TRANSACTION;
FOR iTries IN 1..10 LOOP
BEGIN
UPDATE savings
SET balance = balance - 500
WHERE acct_no = 1234;
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
GOTO e
END;
BEGIN
UPDATE checking
SET balance = balance + 500
WHERE acct_no = 1235;
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN;
END IF;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
GOTO end_of_loop;
END;
BEGIN
INSERT INTO journal (journal_id, tran_tp, credit_account, debit_account,
amount)
VALUES (journal_seq.NEXTVAL, 1, 1234, 1235, 500);
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN;
END IF;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
GOTO
end_of_loop;
END;
EXIT;
<<end_of_loop>>
END
LOOP;
COMMIT;
METHOD TWO - Separate Loops:
CREATE
OR REPLACE PROCEDURE transfer_funds (
p_transfer_from savings.acct_no%TYPE,
p_transfer_to checking.acct_no%TYPE,
p_last_update DATE,
p_amount NUMBER(9,2))
BEGIN
SET TRANSACTION;
FOR iTries IN 1..10
LOOP
BEGIN
UPDATE savings
SET balance = balance - p_amount,
last_update = SYSDATE
WHERE
acct_no = p_transfer_from
AND last_update = p_last_update;
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN;
ELSE
SAVEPOINT
A;
EXIT;
END IF;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
IF (Not recoverable(SQLCODE)) THEN
RETURN;
END IF;
END;
END LOOP;
IF (SQLCODE <> 0 OR
SQL%ROWCOUNT = 0) THEN
RETURN;
END IF;
FOR iTries IN 1..10
BEGIN
UPDATE checking
SET balance = balance
+ p_amount
WHERE acct_no = p_transfer_to;
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN;
ELSE
SAVEPOINT B;
END IF;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK
TO SAVEPOINT A;
IF (Not recoverable(SQLCODE)) THEN
ROLLBACK;
RETURN;
END IF;
END;
END LOOP;
IF (SQLCODE <> 0 OR SQL%ROWCOUNT
= 0) THEN
ROLLBACK;
RETURN;
END IF;
FOR iTries IN 1..10
BEGIN
INSERT
INTO journal (journal_id, tran_tp, credit_account, debit_account, amount)
VALUES (journal_seq.NEXTVAL, 1, p_transfer_from, p_transfer_to, p_amount);
IF (SQL%ROWCOUNT = 0)
THEN
ROLLBACK;
RETURN
ELSE
COMMIT;
EXIT;
END IF;
EXCEPTION
WHEN
OTHERS THEN
ROLLBACK
TO SAVEPOINT B;
IF (Not recoverable(SQLCODE)) THEN
ROLLBACK;
RETURN;
END IF;
END;
END LOOP;
IF (SQLCODE <> 0 OR SQL%ROWCOUNT
= 0) THEN
ROLLBACK;
RETURN;
END IF;
In the first example all
three SQL-Statements are contained within a loop (Transaction Loop) they are then committed only if all
three finish successfully, otherwise the loop will retry up to ten times to get
the transaction to succeeded, if it does not it will finally be rolled
back. The SET TRANSACTION command
is Always before the loop begins and the COMMIT is always after the loop
completes.
In the second example each
statement is given its own loop.
The first SQL-Statement creates a savepoint (A) if it succeeds,
otherwise it is rolled back and retries for a maximum of ten tries. If unsuccessful after ten attempts, the
entire transaction is rolled back and processing returns to the calling
program.
The second SQL-Statement
Creates a savepoint (B) if it succeeds, otherwise it is Rolled back to the
Prior savepoint and retries itself for a maximum of ten tries. If unsuccessful
after ten attempts, the entire transaction is rolled back and processing returns
to the calling program.
Finally the last
SQL-Statement will COMMIT the entire transaction if successful, otherwise it
will rollback to the Prior savepoint and retries itself for a maximum of ten
tries. If unsuccessful after ten attempts, the entire transaction is rolled back
and processing returns to the calling program.
QUERY Flashbacks: Allow you to view state of the database back in a period of time.
Steps:
Grant Permission: GRANT EXECUTE ON SYS.DBMS_FLASHBACK TO store;
EXECUTE DBMS_FLASHBACK.ENABLE_AT_TIME(SYSDATE -10/1440); -- Ten Minutes (24 * 60 = 1440 minutes in a day).
EXECUTE DBMS_FLASHBACK.DISABLE();
Alternatively you can use a System Change Number:
VARIABLE current_scn NUMBER
EXECUTE :current_scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
PRINT current_scn
INSERT INTO products (product_id,
product_type_id, name, description, price)
VALUES (15, 1, 'Back to the Future',
'Complements of the Oracle Time Machine', 39.95);
COMMIT;
SELECT * FROM products WHERE product_id=15;
EXECUTE DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(:current_scn);
SELECT * FROM products WHERE product_id=15;
EXECUTE DBMS_FLASHBACK.DISABLE();