The calculation verbs available are basically the same ones you use in programming: AVG , COMPUTE , COUNT , MAX , MIN , NUM , SUM , STD , and VAR . To produce totals, use the BREAK ON command followed by a COMPUTE statement. In the next example you'll see simple totals. BREAK ON is used to tell Oracle when to skip a line or lines, or start a new page. BREAK ON can take four conditions:
Using the BREAK ON command gets you into advanced reporting. With it you can produce reports , for example, that will list all the exams someone has taken; show the class dates, grades, hours, and then total hours; skip two lines; and go on to the next person. At the end, it can skip to a new page and then print total hours for everyone. As with any other programming tool, you will have to use BREAK ON , make mistakes, learn the nuances , and keep practicing until you're comfortable. Finally, you can create pseudocolumns , make calculations using columns , and get pretty fancy with your reports. (A pseudocolumn is a column that re-ally isn't in the table, such as SYSDATE .) I refer you to further documentation on using the power of SQL*Plus reporting. Let's look at our earlier report, now that it has some totals and uses two tables. We've added the student last name. We also wanted a count for the number of students who have taken the various tests available. Since we ran the first report a couple of minutes ago, several more students have taken various exams. Here's the new report:
And here's the SQL*Plus script for this report: rem rem Tests Taken report rem written by Jerome Engles rem rem purpose: this is an ad hoc report to list all tests taken, rem by type of test rem set headsep ttitle 'All Tests Taken' btitle 'Guerrilla Exams' Column TEST_ID heading 'TestId ' Column TEST_ID format 999999999 Column STUDENT_ID heading 'StudentId ' Column STUDENT_ID format 999999999 Column LOCATION heading 'Location' format a20 trunc Column L_Name heading 'StudentName' format a30 trunc Break on TEST_ID skip 2 compute count of test_id on test_id compute count of student_id on test_id Set LINESIZE 80 Set PAGESIZE 55 Set NEWPAGE 0 SPOOL C:\TEST.LST SELECT TEST_ID, TEST_HISTORY.STUDENT_ID, LOCATION, L_NAME FROM TEST_HISTORY, STUDENTS WHERE TEST_HISTORY.STUDENT_ID = STUDENTS.STUDENT_ID ORDER BY TEST_ID; SPOOL OFF
And here's what the report looks like if the user selects "1" for the test ID (only one student has taken that test so far):
Here's one other important note on Oracle Reports: You can use variables . Suppose you wanted to do something like let your users enter which test they want to report on. Here's how you would do it: In your script, add the PROMPT and SELECT statements, and you will get just the test that your user specifies: ACCEPT XTEST PROMPT 'Enter Test ID: ' SELECT TEST_ID, TEST_HISTORY.STUDENT_ID, LOCATION, L_NAME FROM TEST_HISTORY, STUDENTS WHERE TEST_ID = '&XTEST' AND TEST_HISTORY.STUDENT_ID = STUDENTS.STUDENT_ID ORDER BY TEST_ID;
Now for the sake of completeness, and because you're probably scratching your head, here's the script modified to show the current date and user in the title. Notice that to do this, we had to:
rem rem Tests Taken report rem written by Jerome Engles rem rem purpose: this is an ad hoc report to list all tests taken, rem by type of test rem set headsep ttitle center 'All GUERRILLA EXAM Tests Taken As of ' skip 1 - center XTODAY ' ' XUSER ; SKIP 3 btitle 'Guerrilla Exams' column XTODAY NEW_VALUE XTODAY noprint format a1 trunc column XUSER NEW_VALUE XUSER noprint format a1 trunc Column TEST_ID heading 'TestId ' Column TEST_ID format 999999999 Column STUDENT_ID heading 'StudentId ' Column STUDENT_ID format 999999999 Column LOCATION heading 'Location' format a20 trunc Column L_Name heading 'StudentName' format a30 trunc Break on TEST_ID skip 2 compute count of test_id on test_id compute count of student_id on test_id Set LINESIZE 80 Set PAGESIZE 55 ACCEPT XTEST PROMPT 'Enter Test ID: ' SPOOL C:\TEST.LST SELECT TEST_ID, TEST_HISTORY.STUDENT_ID, LOCATION, L_NAME, TO_CHAR(SYSDATE, 'fmMONTH, DD, YYYY') XTODAY, USER XUSER FROM TEST_HISTORY, STUDENTS WHERE TEST_ID = '&XTEST' AND TEST_HISTORY.STUDENT_ID = STUDENTS.STUDENT_ID ORDER BY TEST_ID; SPOOL OFF;
What's going on? NEW_VALUE is an Oracle construct that lets you put a vari- able, such as SYSDATE , into ttitle or btitle . SYSDATE is the current date automatically maintained by Oracle. The format is DD-MMM-YYfor example, 04-JUN-03. (Remember the pseudocolumn I mentioned earlier, when I gave SYSDATE as an example?) NEW_VALUE moves what you take in the SELECT ... TO_CHAR ... statement into the NEW_VALUE column. In effect, it is a column that you make on the fly; it exists only as long as you run the script, and it really isn't part of any table. Notice that the name of the column, XTODAY , appears in several placesthat is, in the column definition and in the SELECT statements. Here's the output from the script:
There's another SQL*Plus reporting tool that is very useful for quick and dirty scans of the database. For any mainframe or DOS programmers out there, this tool is similar to a line editor or the old Edlin tool. It's called the command-line editor , and you run it from the SQL> prompt. Remember, if you don't save your work, it disappears when you exit SQL! Type in a standard SELECT command, such as 1* SELECT STUDENT_ID, L_NAME, SSNUM from STUDENTS
Now we want to add the first name. Just use the LIST command, followed by the CHANGE command: SQL> LIST SELECT STUDENT_ID, L_NAME, SSNUM from STUDENTS SQL> CHANGE /SSNUM/SSNUM,F_NAME 1* SELECT STUDENT_ID, L_NAME, SSNUM,F_NAME from STUDENTS SQL> LIST 1* SELECT STUDENT_ID, L_NAME, SSNUM,F_NAME from STUDENTS
If your script is on multiple lines, just type "LIST xx", where "xx" is the line number you want to change: SQL> LIST 1 SELECT STUDENT_ID, 2 L_NAME, 3 SSNUM,F_NAME 4 from 5* STUDENTS To add the state, edit just line 3: SQL> LIST 3 3* SSNUM,F_NAME
(Or just type in "3".) Now use "APPEND": SQL> append, state 3* SSNUM,F_NAME , state SQL> list 1 SELECT STUDENT_ID, 2 L_NAME, 3 SSNUM,F_NAME , state 4 from 5* STUDENTS
Here are some other useful commands:
|