SQL Join: Relationship Between Certain Columns in These Tables
SQL Join: Relationship Between Certain Columns in These Tables
in these tables.
SQL JOIN
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
Svendson
Tove
Borgvn 23
Sandnes
Pettersen
Kari
Storgt 20
Stavanger
44678
22456
24562
34764
15
Now we want to list all the persons with any orders. We use the following SELECT statement: SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons INNER JOIN Orders ON Persons.P_Id=Orders.P_Id ORDER BY Persons.LastName The result-set will look like this: LastName Hansen FirstName Ola OrderNo 22456
Hansen
Ola
24562
Pettersen
Kari
77895
Pettersen
Kari
44678
The INNER JOIN keyword returns 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.
Svendson
Tove
Borgvn 23
Sandnes
Pettersen
Kari
Storgt 20
Stavanger
44678
22456
24562
34764
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 FirstName Ola OrderNo 22456
Hansen
Ola
24562
Pettersen
Kari
77895
Pettersen
Kari
44678
Svendson
Tove
The LEFT JOIN keyword returns all the rows from the left table (Persons), even if there are no matches in the right table (Orders).
RIGHT JOIN table_name2 ON table_name1.column_name=table_name2.column_name PS: In some databases RIGHT JOIN is called RIGHT OUTER JOIN.
Svendson
Tove
Borgvn 23
Sandnes
Pettersen
Kari
Storgt 20
Stavanger
44678
22456
24562
34764
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 FirstName Ola OrderNo 22456
Hansen
Ola
24562
Pettersen
Kari
77895
Pettersen
Kari
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).
Hansen
Ola
Timoteivn 10
Sandnes
Svendson
Tove
Borgvn 23
Sandnes
Pettersen
Kari
Storgt 20
Stavanger
44678
22456
24562
34764
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 FirstName Ola OrderNo 22456
Hansen
Ola
24562
Pettersen
Kari
77895
Pettersen
Kari
44678
Svendson
Tove
34764
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.
2)
SQL aggregate functions return a single value, calculated from values in a column. Useful aggregate functions:
AVG() - Returns the average value COUNT() - Returns the number of rows FIRST() - Returns the first value LAST() - Returns the last value MAX() - Returns the largest value MIN() - Returns the smallest value SUM() - Returns the sum
UCASE() - Converts a field to upper case LCASE() - Converts a field to lower case MID() - Extract characters from a text field LEN() - Returns the length of a text field
ROUND() - Rounds a numeric field to the number of decimals specified NOW() - Returns the current system date and time FORMAT() - Formats how a field is to be displayed
2008/10/23
1600
Nilsen
2008/09/02
700
Hansen
2008/09/03
300
Hansen
2008/08/30
2000
Jensen
2008/10/04
100
Nilsen
Now we want to find the average value of the "OrderPrice" fields. We use the following SQL statement: SELECT AVG(OrderPrice) AS OrderAverage FROM Orders The result-set will look like this:
OrderAverage 950
The COUNT() function returns the number of rows that matches a specified criteria.
2008/10/23
1600
Nilsen
2008/09/02
700
Hansen
2008/09/03
300
Hansen
2008/08/30
2000
Jensen
2008/10/04
100
Nilsen
Now we want to count the number of orders from "Customer Nilsen". We use the following SQL statement: SELECT COUNT(Customer) AS CustomerNilsen FROM Orders WHERE Customer='Nilsen' The result of the SQL statement above will be 2, because the customer Nilsen has made 2 orders in total: CustomerNilsen 2
2008/10/23
1600
Nilsen
2008/09/02
700
Hansen
2008/09/03
300
Hansen
2008/08/30
2000
Jensen
2008/10/04
100
Nilsen
Now we want to find the largest value of the "OrderPrice" column. We use the following SQL statement: SELECT MAX(OrderPrice) AS LargestOrderPrice FROM Orders The result-set will look like this: LargestOrderPrice
2000
2008/10/23
1600
Nilsen
2008/09/02
700
Hansen
2008/09/03
300
Hansen
2008/08/30
2000
Jensen
2008/10/04
100
Nilsen
Now we want to find the smallest value of the "OrderPrice" column. We use the following SQL statement: SELECT MIN(OrderPrice) AS SmallestOrderPrice FROM Orders The result-set will look like this:
SmallestOrderPrice 100
2008/10/23
1600
Nilsen
2008/09/02
700
Hansen
2008/09/03
300
Hansen
2008/08/30
2000
Jensen
2008/10/04
100
Nilsen
Now we want to find the sum of all "OrderPrice" fields". We use the following SQL statement: SELECT SUM(OrderPrice) AS OrderTotal FROM Orders The result-set will look like this:
OrderTotal 5700
3) What is PL/SQL?
PL/SQL stands for Procedural Language extension of SQL. PL/SQL is a combination of SQL along with the procedural features of programming languages. It was developed by Oracle Corporation in the early 90s to enhance the capabilities of SQL.
The Declaration section (optional). The Execution section (mandatory). The Exception (or Error) Handling section (optional).
Declaration Section: The Declaration section of a PL/SQL Block starts with the reserved keyword DECLARE. This section is optional and is used to declare any placeholders like variables, constants, records and cursors, which are used to manipulate data in the execution section. Placeholders may be any of Variables, Constants and Records, which stores data temporarily. Cursors are also declared in this section. Execution Section: The Execution section of a PL/SQL Block starts with the reserved keyword BEGIN and ends with END. This is a mandatory section and is the section where the program logic is written to perform any task.
The programmatic constructs like loops, conditional statement and SQL statements form the part of execution section. Exception Section: The Exception section of a PL/SQL Block starts with the reserved keyword EXCEPTION. This section is optional. Any errors in the program can be handled in this section, so that the PL/SQL Blocks terminates gracefully. If the PL/SQL Block contains exceptions that cannot be handled, the Block terminates abruptly with errors. Every statement in the above three sections must end with a semicolon ; . PL/SQL blocks can be nested within other PL/SQL blocks. Comments can be used to document code. How a Sample PL/SQL Block Looks DECLARE Variable declaration BEGIN Program Execution EXCEPTION Exception handling END;
4) What is a Trigger?
A trigger is a pl/sql block structure which is fired when a DML statements like Insert, Delete, Update is executed on a database table. A trigger is triggered automatically when an associated DML statement is executed.
CREATE [OR REPLACE ] TRIGGER trigger_name - This clause creates a trigger with the given name or overwrites an existing trigger with the same name. {BEFORE | AFTER | INSTEAD OF } - This clause indicates at what time should the trigger get fired. i.e for example: before or after updating a table. INSTEAD OF is used to create a trigger on a view. before and after cannot be used to create a trigger on a view. {INSERT [OR] | UPDATE [OR] | DELETE} - This clause determines the triggering event. More than one triggering events can be used together separated by OR keyword. The trigger gets fired at all the specified triggering event. [OF col_name] - This clause is used with update triggers. This clause is used when you want to trigger an event only when a specific column is updated. CREATE [OR REPLACE ] TRIGGER trigger_name - This clause creates a trigger with the given name or overwrites an existing trigger with the same name. [ON table_name] - This clause identifies the name of the table or view to which the trigger is associated. [REFERENCING OLD AS o NEW AS n] - This clause is used to reference the old and new values of the data being changed. By default, you reference the values as :old.column_name or :new.column_name. The reference names can also be changed from old (or new) to any other user-defined name. You cannot reference old values when inserting a record, or new values when deleting a record, because they do not exist. [FOR EACH ROW] - This clause is used to determine whether a trigger must fire when each row gets affected ( i.e. a Row Level Trigger) or just once when the entire sql statement is executed(i.e.statement level Trigger). WHEN (condition) - This clause is valid only for row level triggers. The trigger is fired only for rows that satisfy the condition specified.
Implicit cursors:
These are created by default when DML statements like, INSERT, UPDATE, and DELETE statements are executed. They are also created when a SELECT statement that returns just one row is executed.
Explicit cursors:
They must be created when you are executing a SELECT statement that returns more than one row. Even though the cursor stores multiple records, only one record can be processed at a time, which is called as current row. When you fetch a row the current row position moves to next row.
Both implicit and explicit cursors have the same functionality, but they differ in the way they are accessed.
Implicit Cursors:
When you execute DML statements like DELETE, INSERT, UPDATE and SELECT statements, implicit statements are created to process these statements. Oracle provides few attributes called as implicit cursor attributes to check the status of DML operations. The cursor attributes available are %FOUND, %NOTFOUND, %ROWCOUNT, and %ISOPEN. For example, When you execute INSERT, UPDATE, or DELETE statements the cursor attributes tell us whether any rows are affected and how many have been affected. When a SELECT... INTO statement is executed in a PL/SQL Block, implicit cursor attributes can be used to find out whether any row has been returned by the SELECT statement. PL/SQL returns an error when no data is selected.
The status of the cursor for each of these attributes are defined in the below table.
Attributes
Return Value The return value is TRUE, if the DML statements like INSERT, DELETE and UPDATE affect at least one row and if SELECT .INTO statement return at least one row. The return value is FALSE, if DML statements like INSERT, DELETE and UPDATE do not affect row and if SELECT.INTO statement do not return a row.
Example SQL%FOUND
%FOUND
%NOTFOUND The return value is FALSE, if DML statements like INSERT, DELETE and UPDATE at least one row and if SELECT .INTO statement return at least one row. The return value is TRUE, if a DML statement like INSERT, DELETE and UPDATE do not affect even one row and if SELECT .INTO statement does not return a row. %ROWCOUNT Return the number of rows affected by the DML operations INSERT, DELETE, UPDATE, SELECT
SQL%NOTFOUND
SQL%ROWCOUNT
For Example: Consider the PL/SQL Block that uses implicit cursor attributes as shown below:
DECLARE var_rows number(5); BEGIN UPDATE employee SET salary = salary + 1000; IF SQL%NOTFOUND THEN dbms_output.put_line('None of the salaries where updated'); ELSIF SQL%FOUND THEN var_rows := SQL%ROWCOUNT; dbms_output.put_line('Salaries for ' || var_rows || 'employees are updated'); END IF; END;
In the above PL/SQL Block, the salaries of all the employees in the employee table are updated. If none of the employees salary are updated we get a message 'None of the salaries where updated'. Else we get a message like for example, 'Salaries for 1000 employees are updated' if there are 1000 rows in employee table.
You need to have read the chapter Start Here for the Tutorials and worked through the first session, Using NetExpress, before you do this session.
6.1 Overview
Using the Data Tools, you can examine data files to see how an application has updated them, or create and edit a file to provide test data for an application. Files can be in any COBOL format and you can view them at
both the record and field levels. You can convert between formats and character sets. The demo application used in this session consists of a data file and the COBOL source program that maintains it. The data file is a variable length sequential file, containing details of staff in three record types: employee, manager and executive. In this session you convert it to a variable length indexed sequential file, and then view it in various ways, formatted and unformatted, using Data File Editor.
6.2 Preparation
If you have closed NetExpress, open it as before. If any project window or other windows are open, close them. To save you creating a project, we have supplied one - click Open on the File menu, and open d:\NetExpress\Base\Demo\Dtoldemo\dtoldemo.app. You'll see the .cbl and .dat files in the project window.
Convert a file View a data file unformatted Create a record layout file Create the default record layout Create the conditional record layouts Save the record layout file View a data file formatted View files in hexadecimal Print a data file Edit multiple data files Create a new data file
To supply the input file details click on the Browse button and use the Open dialog box to select the file datavseq.dat (the dialog box should open at the right folder, d:\NetExpress\Base\Demo\Dtoldemo). The details for the the input file and the output file are initialized with the information read from the file header for datavseq.dat.
2. In the lower part of the dialog box, enter the following details for the output file (leave the remaining fields unchanged): Filename Format Organization d:\NetExpress\Base\Demo\Dtoldemo\staff.dat Micro Focus Indexed Sequential
The field to be used as the key is at the beginning of the record, and is seven bytes long.
5. Set Key Offset to 0 and Key Length to 7, then click OK. 6. Click Convert. 7. Click OK on the message saying the data file conversion is complete, then click OK on the message reporting the results of the conversion.
The Data File Convert dialog box reappears so you can convert more files.
8. Click Cancel. 9. Look in the project window. NetExpress has added the new file staff.dat to the project automatically.
A message box appears, explaining that all edits to indexed and relative file types are applied immediately.
2. To prevent this message appearing again, click in the check box to add a check mark against the prompt Do not show this message again. 3. Click OK.
A Data File Editor window appears displaying the contents of staff.dat, as shown in Figure 6-1.
Figure 6-1: The IDE with a Data File Editor Window Each record is shown as one line. Because Data File Editor does not know the lengths of the fields in the record, each line is simply a continuous line of text - the records are unformatted. Non-character fields such as COMP items generally display as non-standard characters or, if they don't correspond to any printable character, as . You can edit the file by typing over the existing data. There are many editing facilities available. For example, from the Data Tools option on the Search menu, there are three ways of searching a data file:
Data File Find and Replace Find On Indexed Key Goto Record
The status line at the bottom of the IDE shows various statistics, depending on the file details:
Relative record number (relative files only) Length of the selected record, followed by (minimum length, maximum length) if variable length. Number of records (sequential files only) Cursor position - line number and column position, both starting at 0.
The Data File Editor window may have a right-hand pane visible, displaying "A record layout file must be loaded before using this window". We'll see in a later section what this is for. You can see the file's properties in full:
1. Right-click in the Data File Editor window. 2. Click File Information on the popup menu.
The File Information window displays information such as the file format and organization.
3. To view more information about the file, click on the Keys and General tabs. 4. When you have finished, click on Cancel to close the File Information window. 5. Leave the Data File Editor window open to use later in this tutorial. 6.3.3 Creating a Record Layout File
The Data File Editor can display file contents formatted, if it knows the layout of the fields. You create a record layout file from the Data Division of a COBOL program that uses the file. You must have compiled the program to create the necessary information. Our data file staff.dat has three record types: employee, manager, and executive. You have to tell Data File Editor the layout of each type of record,
and how to identify the type. You define one type to be the default. The others are called conditional. To create a record layout file:
1. Select the project window. 2. Right-click dfdstaff.cbl in the left-hand pane of the project window, and click Compile on the popup menu. 3. Right-click dfdstaff.cbl again and click Create Record Layout on the popup menu.
A Record Layout Editor window opens. This window displays a tree view of the data division of dfdstaff.cbl.
6.3.4 Creating the Default Record Layout
Default Layout should be set automatically as you have already defined a default layout.
3. If it is not, click Default Layout to set EMPLOYEE-REC as the default record layout. 4. Click Next, then click Finish.
Conditional Layout is set automatically as you have already defined a default layout.
2. Click Next, then click Finish, to add MANAGER-REC as a conditional layout.
A folder for MANAGER-REC appears in the right-hand pane. You now need to specify the field and condition that identify the record type.
3. In the right-hand pane, expand the MANAGER-REC folder by clicking its "+", then expand the 01 MANAGER-REC entry by clicking its "+", then expand the 02 MN-CODE entry by clicking its "+". 4. In the right-hand pane, right-click 03 MN-POSITION, then click Properties on the popup menu.
M indicates a Manager record type. The two characters below the dotted line are the hexadecimal equivalent, arranged vertically. They should be "4" and "D", since M in ANSI is hex 4D.
7. Click OK.
The Save As dialog box appears. The folder defaults to d:\NetExpress\Base\Demo\Dtoldemo. The filename defaults to dfdstaff.str, which is the COBOL program name with a .str extension. When Data File Editor loads a data file, it looks in the same folder for a record layout file with the same name as the data file and with
extension .str. In a simple application where the data file has the same name as the COBOL program, apart from the extension, this default of the program name with .str extension is appropriate.
2. Now our data file is named staff.dat and therefore requires a record layout file named staff.str. (Remember, we used the Data File Converter to convert datavseq.dat to staff.dat.) Therefore, change the File Name field for the record layout file to staff.str. Then click Save. 3. Close the Record Layout Editor window by clicking Close on the File menu. 6.3.7 Viewing a Data File Formatted
A new right-hand pane appears. The left-hand pane contains the unformatted view of multiple records, one per line, that you had before. In the right-hand pane, Data File Editor has applied the formatting information from the record layout file. This pane shows a formatted view of a single record. The record layout name is at the top of the pane. At the top right are two navigation controls: the small up-arrow takes you to the previous record and the small down-arrow takes you to the next record. You can edit a record by clicking in the Value column and typing over the existing data. The editing facilities mentioned earlier for the unformatted view are available in the formatted view too.
4. Click in the left-hand pane, and move the cursor over the records in the unformatted view
Notice how the formatted view alters, matching the record types as you move through the file.
You can use Data File Editor to view and edit your data in hexadecimal:
1. Right-click in the Data File Editor window (either pane) and click Show Hex on the popup menu.
New panes appear at the bottom of the window. The left-hand pane shows the selected record from the top left-hand pane, with the hex beneath. For elementary field items only, the right-hand pane shows the selected field from the top right-hand pane, with the hex beneath. Otherwise, the right hand pane displays a text description such as Group item. Each pair of hex digits is arranged vertically. For example, when you edit ANSI data, an M is shown in hex as "4" with a "D" beneath. If you can't see both lines of hex, make the window bigger by dragging its bottom edge downward.
2. Right-click within the Data File Editor window and click Show Hex on the popup menu.
The check mark by this menu item disappears, and the hex panes disappear.
6.3.9 Printing a Data File
You can print a data file from Data File Editor using the Print function, or use the Print Preview function to display it on screen as it would appear when printed. You can choose the formatted or unformatted view. You can choose whether to print the current record, all records or partial records. To preview a print of the unformatted view of a data file:
1. Click in the left-hand pane of the Data File Editor window, then click Print Setup on the File menu. 2. Set Orientation to Landscape, then click OK. 3. Select Print Preview on the File menu. 4. Check the checkbox beside Header Text and specify the heading text as Print of Data File STAFF.DAT.
5. Put check marks by: o Page numbers o Ruler o Record Numbers o Hexadecimal Values
and select:
All Records Whole Record 6. Click Preview.
o o
A Preview window appears. You can use the buttons on the toolbar to zoom in and out, move around the window, and print.
7. Click Close on the buttonbar of the Preview window. 6.3.10 Editing Multiple Data Files
As with many of the editors in NetExpress, you can use Data File Editor to edit several files at once, choosing various ways to position their windows within the IDE. To edit two data files, putting their windows one above the other:
1. From the project window, double click on the file datavseq.dat.
A new Data File Editor window opens for datavseq.dat. Only the unformatted pane appears, as no record layout is associated with this file.
2. Minimize the project window by clicking its button. 3. Select Tile Horizontally on the Window menu.
You can now see the Data File Editor windows for both datavseq.dat and staff.dat
4. Toggle between the windows by clicking alternatively on the tags for datavseq.dat and staff.dat near the bottom of the NetExpress window. 5. Close both Data File Editor windows. Restore the project window to its normal size (click the button).
Since a fixed length sequential does not have a file header, NetExpress prompts you to save the file header details you have just entered in a profile file. Creating a profile saves you having to enter the file header details next time you open the data file.
3. Click Yes.
NetExpress saves the profile in a profile file in the same directory as the data file. Profile files have the same filename as the data file with a .pro extension. Therefore, the profile file for this new data file is named newfile.pro. A Data File Editor window appears. It displays "File Empty". Let's add and delete a few records.
4. Right-click in the Data File Editor window, then click Insert Record After on the popup menu.
The new record is deleted from the file and the cursor is positioned on the previous record.
8. Click Save on the File menu. 9. Close the Data File Editor window