Download presentation
Presentation is loading. Please wait.
1
Embedded SQL Chapter 8
2
SQL in Real Programs We have seen only how SQL is used at the generic query interface --- an environment where we sit at a terminal and ask queries of a database. Reality is almost always different. Programs in a conventional language like C are written to access a database by “calls” to SQL statements.
3
Host Languages Any conventional language can be a host language, that is, a language in which SQL calls are embedded. The use of a host/SQL combination allows us to do anything computable, yet still get the very-high-level SQL interface to the database.
4
Connecting SQL to the Host Language
Embedded SQL is a standard for combining SQL with seven languages. CLI (Call-Level Interface ) is a different approach to connecting C to an SQL database. JDBC (Java Database Connectivity ) is a way to connect Java with an SQL database.
5
Embedded SQL Key idea: Use a preprocessor to turn SQL statements into procedure calls that fit with the host-language code surrounding. All embedded SQL statements begin with EXEC SQL, so the preprocessor can find them easily.
6
Host language compiler
Programs with SQL Host language + Embedded SQL Preprocessor Preprocessor Host Language + function calls Host language compiler Host language compiler Host language program
7
The Impedance Mismatch Problem
The host language manipulates variables, values, pointers SQL manipulates relations. There is no construct in the host language for manipulating relations. Why not use only one language? Forgetting SQL: definitely not a good idea! SQL cannot do everything that the host language can do.
8
Embedded SQL Use host language as front-end. Use SQL to access statements to access database. Preprocessor translates SQL statements to lib function calls. Values get passed through shared variables. Colons precede shared variables when they occur within the SQL statements. EXEC SQL: precedes every SQL statement in the host language. A special variable SQLSTATE provides error messages and status reports (e.g., says that the operation completed with noproblem).
9
Embedded SQL: Declarations
EXEC SQL BEGIN DECLARE SECTION; char productName[30]; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; SQLSTATE: each SQL operation returns a 5-digit code indicating the status of the operation: e.g. “00000” no error “02000” no more tuples
10
Embedded SQL: Using Shared Variables
void simpleInsert() { EXEC SQL BEGIN DECLARE SECTION; char productName[20], company[30]; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; /* get values for productName and company somehow */ EXEC SQL INSERT INTO Product(name, company) VALUES (:productName , :company); }
11
Embedded SQL: Queries Updates can be done as shown in previous example
SQL Queries (i.e. Select) Impedance mismatch Two cases: Query returns a single row Query returns multiple rows
12
Single-Row Select Statements
Void getPrice() { EXEC SQL BEGIN DECLARE SECTION; char productName[20], company[30]; integer qty, float price; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; /* read value of product name */ EXEC SQL SELECT price, qty_on_hand INTO :price, :qty FROM Product WHERE Product.name = :productName; /* print out value of price and qty */ }
13
Cursors A cursor is a tuple-variable that ranges over all tuples in a table or the result of a query. Declare cursor: EXEC SQL DECLARE cursor_name CURSOR FOR <Query>/<table>; To use cursor, must issue command: EXEC SQL OPEN cursor_name; When finished with cursor, close it: EXEC SQL CLOSE cursor_name;
14
Cursors EXEC SQL DECLARE cursorName CURSOR FOR
SELECT …. FROM …. WHERE …. ; EXEC SQL OPEN cursorName; while (true) { EXEC SQL FETCH FROM cursorName INTO :variables; if (NO_MORE_TUPLES) break; /* do something with values */ } EXEC SQL CLOSE cursorName;
15
Breaking Cursor Loop if (NO_MORE_TUPLES) break;
NO_MORE_TUPLES is a macro defined as: #define NO_MORE_TUPLES !(strcmp(SQLSTATE,“02000”));
16
Example How many books are priced above $100?
Note: we could write this as a simple SQL Select statement void CheckPrices( ) { EXEC BEGIN DECLARE SECTION ; int counter; float price; char SQLSTATE[6]; EXEC END DECLARE SECTION ; #define NO_MORE_TUPLES !(strcmp(SQLSTATE,“02000”));
17
Cursors --Example EXEC SQL DECLARE BookPriceCur CURSOR FOR
Select price from titles ; EXEC SQL OPEN BookPriceCur; counter = 0; while (true) { EXEC SQL FETCH FROM BookPriceCur INTO :price; if (NO_MORE_TUPLES) break; if (price > 100) ++counter; } EXEC SQL CLOSE cursorName; Printf(“Books priced over $100: %d\n”, counter);
18
More on Cursors Cursors can be used to modify a relation as well as read it. Cursor must be defined on a based table We can determine the order in which the cursor will get tuples by the ORDER BY keyword in the SQL query. Cursors can be protected against changes to the underlying relations. The cursor can be a scrolling one: can go forward, backward +n, -n, Abs(n), Abs(-n).
19
Example Increase all CS books by 50% EXEC BEGIN DECLARE SECTION ;
void IncreaseCS( ) EXEC BEGIN DECLARE SECTION ; char title_id[7], title[30]; float price; char type[20]; int ytd_sales; flaot advance; char pub_id[9], ed_id[9]; char SQLSTATE[6]; EXEC END DECLARE SECTION ; #define NO_MORE_TUPLES !(strcmp(SQLSTATE,“02000”));
20
Cursors --Example EXEC SQL DECLARE titlesCur CURSOR FOR titles;
EXEC SQL OPEN titlesCur; while (true) { EXEC SQL FETCH FROM titlesCur INTO :title_id, :title, :price, :type, :pubdate, :ytd_sales, :advance, :pub_id, :ed_id; if (NO_MORE_TUPLES) break; if ( !(strcmp(type, ‘CS’) ) EXEC SQL UPDATE titles Set price = 0.5 * price WHERE CURRENT OF titlesCur; } EXEC SQL CLOSE titlesCur ;
21
Protecting Against Concurrent Updates
EXEC SQL DECLARE cursor_name INSENSITIVE CURSOR FOR <Table>; SQL system will guarantee the changes made to Table between one opening and closing of the cursor will not affect the set of tuples fetched by any other query.
22
Dynamic SQL generic query interface that allows the user to issue ad-hoc queries Queries are not known until run time.
23
Dynamic SQL Preparing a query:
EXEC SQL PREPARE <query_name> FROM <string>; Execute the query EXEC SQL EXECUTE <query_name> Prepare: generates optimized plan for the query prepare one, execute many time
24
Example: A Generic Query Interface
EXEC SQL BEGIN DECLARATION SECTION; char query[Max_Length] EXEC SQL END DECLARATION SECTION; WHILE (1) { /* issue SQL> Prompt */ /* Read user query into array query[] */ EXEC SQL PREPARE q FROM query; EXEC SQL EXECUTE q; }
25
EXECUTE IMMEDIATE If we are to execute the query only once, the prepare and execute steps can be combined into one. EXEC SQL EXECUTE IMMEDIATE <string>;
26
Stored Procedures SQL/PSM
27
Stored Procedures Extension to SQL called SQL/PSM or “persistent, stored modules” Allows us to store procedures as database schema elements Programming style is mixture of conventional statements (if, loops, etc.) and SQL
28
Basic PSM Forms Procedures
CREATE PROCEDURE <name> (<parameters_list>) <optional local declarations> <body>; Functions CREATE FUNCTION <name> (<parameters_list>) RETURNS <type>
29
Parameter List PSM uses mode-name-type triples, where mode can be
IN : procedure uses value, does not change it OUT: procedure changes value, does not use INOUT : both
30
Example Let’s assume we have a table Products
Products(p_num, p_desc, p_price) Write a procedure that takes three arguments A, B and C, and adds a tuple to Products that has p_num=A, p_desc=B and p_price=C
31
Example Create Procedure AddProduct(IN A char(7), IN B char(30), IN C REAL) BEGIN INSERT INTO Products VALUES (A, B, C); END
32
Invoking Procedures Use SQL/PSM statement CALL, with the name of the desired procedure and arguments Example CALL AddProdcut(‘ ’, ‘Laptop-752’, ); Functions are used in SQL expressions where a value of their return type is appropriate
33
PSM Statements DECLARE <name> <type>
Used to declare local variables e.g. Declare X INTEGER BEGIN … END Used to delimit groups of statements Statements are separated by semicolons RETURN <expression> Sets the return value of a function Unlike C, it does not return control to calling procedure Statement Labels: prefix with a name and a colon
34
PSM Statements CNTND Assignment Statements IF statements Loops Queries
35
Assignment Statements
SET <variable> = <expression> E.g.: SET p_id = ‘ ’; SET p_price = ;
36
IF Statements Simple form: IF <condition> THEN
ENDIF; With ELSE part IF <condition> THEN <statement(s)> ELSE <statement(s)> With ELSEIFs IF …THEN … ELSEIF …THEN …ELSEIF… THEN…. ELSE … ENDIF;
37
Example--IF Let’s write a function that rates the popularity of a book based on its year to date sales: < 100 copies sold: not popular 100 to 1000: average > 1000: popular
38
Example--IF CREATE FUNCTION Rate(IN B CHAR(30)) RETURNS CHAR(10)
DECLARE copies INTEGER; BEGIN SET copies = (Select ytd_sales from titles Where title=B); IF copies < 100 THEN RETURN ‘unpopular’; ELSEIF copies <= 1000 THEN RETURN ‘average’; ELSE RETURN ‘popular’; END IF; END; /* return occurs here not at one of the return statements
39
Declaring SQLSTATE Condition
We can declare a condition variable associated with SQLSTATE. Example: DECLARE No_More_Tuples CONDITION FOR SQLSTATE ‘02000’; …. IF No_More_Tuples THEN …. Syntax: DECLARE <name> CONDITION FOR SQLSTATE <value>;
40
Loops Basic form: LOOP <statement(s)> END LOOP;
Exit from a loop by: LEAVE <loop label> The <loop label> is associated with a loop by prefixing the keyword LOOP with a label and a colon.
41
Example--LOOP LP1: LOOP …. LEAVE LP1; END LOOP;
42
Other Loop Forms WHILE DO loop: WHILE <condition> DO
<Statement(s)> END WHILE; REPEAT UNTIL loop: REPEAT <Statement(s)> UNTIL <condition> END REPEAT;
43
QUIRIES Three ways queries are used:
Queries producing one value can be used in an expression e.g. Assignment statement Queries that return a single row SELECT … INTO (same as in embedded SQL) Using Cursors
44
Single Value Queries SET copies = (Select ytd_sales from titles
Where title_id = ‘121212’);
45
Single Row Queries CREATE Procedure GetAuthorInfo( IN id Char(10), OUT phone# Char(10), OUT address Char(30), OUT city Char(10), OUT state Char(2) ) Select phone, address, city, state INTO phone#, address, city, state From authors Where authors.au_id = ID;
46
Cursors Cursors are used the same way as in embedded SQL with the following differences: No EXEC SQL prefix in statements Variables do not use colon prefix
47
Example How many books are priced above $100?
Note: we could write this as a simple SQL Select statement CREATE PROCEDURE ExpensiveBooks(OUT counter INTEGER ) DECLARE No_More_tuples CONDITION FOR SQLSTATE ‘02000’; DECLARE price REAL; DECLARE BookPriceCur CURSOR FOR Select price from titles ;
48
Cursors --Example BEGIN OPEN BookPriceCur; counter = 0; BPLoop: LOOP
FETCH FROM BookPriceCur INTO price; IF NO_MORE_TUPLES THEN LEAVE BPloop END IF; IF price > 100 THEN ++counter END IF; END LOOP; CLOSE BookPriceCur; END;
49
Connecting SQL to a host language
Embedded SQL: is a standard for connecting SQL to ~ seven programming languages Call-Level Interface (CLI): provides a different approach to connecting C to SQL databases JDBC (Java DataBase Connectivity): is a way to connect Java programs to SQL databases
50
SQL/CLI: Call-Level Interface
Chapter 8
51
SQL/CLI Embedded SQL: SQL statements are prefixed with EXEC SQL
Preprocessor transforms all SQL statements before host program is compiled SQL/CLI: Uses a library of functions which are called by C code dynamically. The library for C is called SQL/CLI Embedded SQL preprocessor translated the EXEC SQL statements into CLI calls.
52
Data Structures C connects the database of structs of the following types: Environments: represents the DBMS installation Connections: logins to the database Statements: hold SQL statements to be passed to a connection Descriptions: records about tuples of a query or statement parameters
53
Environments, Connections, Statements
Function SQLAllocHandle(T, I,O) is used to create these data structures which are called environment, connection, and statement handles T : type e.g. SQL_HANDLE_STMT I : Input Handle = struct at next higher level O: (address of) output handle
54
Example #include sqlcli.h SQLHENV myEnv; SQLHDBC myCon;
SQLHSTMT myStat; SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &myEnv); SQLAllocHandle(SQL_HANDLE_DBC, myEnv, &myCon); SQLAllocHandle(SQL_HANDLE_STMT, myCon, &myStat);
55
Example #include sqlcli.h SQLHENV myEnv; SQLHDBC myCon;
SQLHSTMT myStat; SQLRETURN errCode1, errCode2, errCode3; errCode1 = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &myEnv); if (!errCode1) errCode2 = SQLAllocHandle(SQL_HANDLE_DBC, myEnv, &myCon); else // run error handler if (!errCode2) errCode3 = SQLAllocHandle(SQL_HANDLE_STMT, myCon, &myStat);
56
Preparing and Executing a Statement
SQLPrepare(H, S, L): causes the string S, of length L, to be interpreted as an SQL statement and the executable statement is placed in statement handle H. SQLExecute(H): causes the SQL statement represented by statement handle H to be executed.
57
Example SQLPrepare(myStat, “Select title, price
From authors Where type = ‘CS’ “, SQL_NTS); SQL_NTS the second argument is a null-terminated string (figure out its length). SQLExecute(myStat);
58
Dynamic Execution If a statement S is to be executed only once, we can combine Prepare and Execute with: SQLExecuteDirect(H, S, L); H is a statement handle L is the length of string S
59
Fetching Data From Output of a Query
When the SQL statement is a query (i.e. a Select statement), we need to fetch the data from the output of the statement SQLFetch(H) gets the next tuple from the result of executing the statement with handle H. A cursor is implied and no need to declare it.
60
Binding attribute values to variables
When we fetch a tuple, we need to put the components somewhere. The function SQLBindCol is used to bind each component of the fetched tuple to a variable. SQLBindCol(H, colNo, colType, varAddr, varSize, varInfo) H: handle of the query statement colNo: column number varAddr: Address of the variable
61
Example: Binding Suppose we have just done SQLExecute(myStat) where myStat is the handle for query Select title, price From titles Where type = ‘CS’ And suppose BookTitle is declare to be of type string and P a variable of type float SQLBindCol(myStat, 1, , BookTitle, , ); SQLBindCol(myStat, 2, , &P, , );
62
Example: Fetching After binding tuple attributes to variables, data can be fetched from the tuples one tuple at a time: while (SQLFetch(myStat) != SQL_NO_DATA ) { /*do something with BookTitle and P */ } SQL_NO_DATA: CLI macro representing SQLSTATE=“02000”
63
JDBC Java Database Connectivity (JDBC) is a library similar to SQL/CLI, but with Java as the host language. JDBC/CLI differences are mostly related to the object-oriented style of Java.
64
JDBC When JDBC driver is installed, it creates an object called DriverManager. DriverManager is analogous to environment variable in CLI First create a connection using method getConnection of the DriverManager Connection myCon = DriverManger.getConnection(<URL>, <name>, <password>);
65
Creating Statements in JDBC
Two connection methods can be used to create statements: createStatement(): returns an object of type Statement. It has no SQL statement associated with it prepareStatement(Q): Q is an SQL statement passed as a string, returns an object of type PreparedStatement.
66
Example: Creating Statements
Statement stat1 = myCon.createStatement(); PrepapredStatement stat2 = myCon.createStatement( “SELECT title, price “ + “From titles Where type = ‘CS’ ” );
67
Executing SQL Statements
JDBC distinguishes queries from modifications, which it calls “updates” There are 4 methods for executing SQL statements. They differ on whether the statement is of type Statement or PreparedStatement a query or an “update”
68
Executing SQL Statements
excuteQuery(Q): Q is a query statement is applied to a Statement object. Returns an object of type ResultSet executeQuery(): is applied to a PreparedStatement object. Returns an object of type ResultSet. excuteUpdate(U): U is a nonquery statement. When applied to a Statement object, U is executed. No result set is returned. excuteUpdate(U): is applied to a PrepaedStatement object
69
Example: Update Stat1 is a Statement object. We can use it to insert a tuple as: Stat1.executeUpdate( “INSERT INTO titles” + “ VALUES(‘111111’, ‘Intro to DB’, ‘CS’, 98)” );
70
Example: Query Stat2 is a PreparedStatement holding the query “Select title, price From titles Where type=‘CS’ ”. executeQuery returns an object of class ResultSet. ResultSet CsBooks = stat1.executeQuery();
71
Accessing the ResultSet
An object of type ResultSet is like a cursor Method Next() advances the “cursor” to the next tuple. The first time Next() is applied, it gets the first tuple. Subsequently, it get the next tuple in order. If there are no more tuples, Next() returns False
72
Access Attribute Values of Tuples
When a ResultSet is referring to a tuple, we can get the tuple’s components by applying certain methods to the ResultSet. Method getX(i), where X is some type, and i is the component number, returns the value of that component. The value must be of type X. E.g. getString(2): returns string value of 2nd column of tuple.
73
Example: Accessing Compnents
CsBooks is the ResultSet for the example query. We can access the title and price of each tuple while (CsBooks.Next() ) { BookTitle = CsBooks.getString(2); P = CsBooks.getFloat(4); /*Do something with BookTitle and P */ }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.