#Accessing SQL From a Programming Language
- JDBC: Java Database Connectivity
- ODBC: Open Database Connectivity
- Embedded SQL ...
EXEC-SQL connect to server_addr user user_name using password; EXEC SQL <embedded SQL statement > END_EXEC EXEC SQL declare c cursor for select ID, name from student where tot_cred > :credit_amount END_EXEC
#Extensions and stored procedures
SQL provides a module language
- Permits definition of procedures in SQL, with if-then-else statements, for and while loops, etc.
- Can store procedures in the database
- then execute them using the call statement
- permit external applications to operate on the database without knowing about internal details
Define a function that, given the name of a department, returns the count of the number of instructors in that department.
Find the department name and budget of all departments with more that 12 instructors.
create function dept_count(dept_name varchar(20)) returns integer begin declare d_count integer; select count(*) into d_count from instructor where instructor.dept_name = dept_name return d_count; end select dept_name, budget from department where dept_count(dept_name) > 1
- May contain multiple SQL statements between begin and end.
- returns -- indicates the variable-type that is returned (e.g.,integer)
- return -- specifies the values that are to be returned as result of invoking the function
- SQL function are in fact parameterized views that generalize the regular notion of views by allowing parameters.
Example: Return all accounts owned by a given customer
create function instructors_of(dept_name char(20) returns table (ID varchar(5), name varchar(20), dept_name varchar(20), salary numeric(8,2)) return table ( select ID, name, dept_name, salary from instructor where instructor.dept_name = instructors_of.dept_name ) select * from table (instructors_of (‘Music’))
The dept_count function could instead be written as procedure:
create procedure dept_count_proc (in dept_name varchar(20), out d_count integer) begin select count(*) into d_count from instructor where instructor.dept_name = dept_count_proc.dept_name end
Procedures can be invoked either from an SQL procedure or from embedded SQL, using the call statement.
declare d_count integer; call dept_count_proc( ‘Physics’, d_count);
SQL:1999 allows more than one function/procedure of the same name (called name overloading), as long as the number of arguments differ, or at least the types of the arguments differ
#Language Constructs for Procedures & Functions
SQL supports constructs that gives it almost all the power of a general-purpose programming language.
Warning: most database systems implement their own variant of the standard syntax below.
Compound statement: begin … end,
- May contain multiple SQL statements between begin and end.
- Local variables can be declared within a compound statements
While and repeat statements:
while boolean expression do sequence of statements ; end while
repeat sequence of statements ; until boolean expression end repeat
A trigger is a statement that is executed automatically by the system as a side effect of a modification to the database.
To design a trigger mechanism, we must:
- Specify the conditions under which the trigger is to be executed.
- Specify the actions to be taken when the trigger executes.
Triggers introduced to SQL standard in SQL:1999, but supported even earlier using non-standard syntax by most databases.
- Triggering event can be insert, delete or update
- Triggers on update can be restricted to specific attributes
- after update of takes on grade
- Values of attributes before and after an update can be referenced
- referencing old row as: for deletes and updates
- referencing new row as: for inserts and updates
- Triggers can be activated before an event, which can serve as extra constraints. E.g. convert blank grades to null.
create trigger setnull_trigger before update of takes referencing new row as nrow for each row when (nrow.grade = ' ') begin atomic set nrow.grade = null; end; create trigger credits_earned after update of takes on (grade) referencing new row as nrow referencing old row as orow for each row when nrow.grade <> 'F' and nrow.grade is not null and (orow.grade = 'F' or orow.grade is null) begin atomic update student set tot_cred= tot_cred + (select credits from course where course.course_id= nrow.course_id) where student.id = nrow.id; end;
#Statement level triggers
Instead of executing a separate action for each affected row, a single action can be executed for all rows affected by a transaction
for each statement instead of
for each row
referencing old table or
referencing new table to refer to temporary tables (called
transition tables) containing the affected rows
Can be more efficient when dealing with SQL statements that update a large number of rows
#When Not To Use Triggers
Triggers were used earlier for tasks such as
- maintaining summary data (e.g., total salary of each department)
- Replicating databases by recording changes to special relations (called change or delta relations) and having a separate process that applies the changes over to a replica
There are better ways of doing these now:
- Databases today provide built in materialized view facilities to maintain summary data
- Databases provide built-in support for replication
Encapsulation facilities can be used instead of triggers in many cases
- Define methods to update fields
- Carry out actions as part of the update methods instead of through a trigger
Risk of unintended execution of triggers, for example, when
- loading data from a backup copy
- replicating updates at a remote site
- Trigger execution can be disabled before such actions.
Other risks with triggers:
- Error leading to failure of critical transactions that set off the trigger
- Cascading execution
#Recursion in SQL
SQL:1999 permits recursive view definition
Example: find which courses are a prerequisite, whether directly or indirectly, for a specific course.
with recursive rec_prereq(course_id, prereq_id) as ( select course_id, prereq_id from prereq union select rec_prereq.course_id, prereq.prereq_id, from rec_rereq, prereq where rec_prereq.prereq_id = prereq.course_id ) select ∗ from rec_prereq;
#Advanced Aggregation Features
Ranking is done in conjunction with an order by specification.
select ID, rank() over (order by GPA desc) as s_rank from student_grades order by s_rank
Ranking may leave gaps: e.g. if 2 students have the same top GPA, both have rank 1, and the next rank is 3. dense_rank does not leave gaps, so next dense rank would be 2.
Ranking can be done using basic SQL aggregation, but resultant query is very inefficient.
select ID, (1 + (select count(*) from student_grades B where B.GPA > A.GPA)) as s_rank from student_grades A order by s_rank;
Ranking can be done within partition of the data.
select ID, dept_name, rank () over (partition by dept_name order by GPA desc) as dept_rank from dept_grades order by dept_name, dept_rank;
Multiple rank clauses can occur in a single select clause.
Ranking is done after applying group by clause/aggregation
Used to smooth out random variations.
Example: moving average: “Given sales values for each date, calculate for each date the average of the sales on that day, the previous day, and the next day”
Window specification in SQL:
select date, sum(value) over (order by date between rows 1 preceding and 1 following) from sales