M.P. Johnson, DBMS, Stern/NYU, Spring C : Database Management Systems Lecture #16 M.P. Johnson Stern School of Business, NYU Spring, 2005
M.P. Johnson, DBMS, Stern/NYU, Spring Agenda Go over midterm NYU Infrastructure Programming for SQL Live examples
M.P. Johnson, DBMS, Stern/NYU, Spring Midterm Info Possible:129 Mean:116 Stdev:9.7
M.P. Johnson, DBMS, Stern/NYU, Spring Agenda Before break:: Views, Constraints, Midterm This time: Begin programming for SQL Embedded SQL Pro*C, SQLJ CLI SQL/CLI in C JDBC in Java DBI/DBDs in Perl Future: PL/SQL, Triggers
M.P. Johnson, DBMS, Stern/NYU, Spring Querying tables Given: Emp(ename,empno,mgr,etc.) How to get list of bosses & subordinates?
M.P. Johnson, DBMS, Stern/NYU, Spring R.A./SQL has limitations Can easily find Alice’s direct subordinates: But: find all of King’s underlings Cannot compute “transitive closure” Cannot express in R.A./SQL! SQL is not “Turing-Complete” NameJobBoss KingPresidentNULL JonesManagerKing BlakeManagerKing FordAnalystJones ScottAnalystJones
M.P. Johnson, DBMS, Stern/NYU, Spring New topic: SQL Programming Can write SQL queries in a SQL interpreter Command prompt SQL*Plus (sqlplus) in Oracle mysql in MySQL Good for experimenting, not for anything non-trivial Better: use a standard programming language Host language talks to SQL/DB
M.P. Johnson, DBMS, Stern/NYU, Spring Using two languages Q: Why not use just one language? “[W]e can quickly dispense with the idea…” (Ullman, p351) Q: Why not do everything in SQL? A: Not designed as a general-purpose language No recursion (no factorial!), not Turing-complete No, e.g., Swing library Q: Why not do everything in the host lang.? A: What Oracle provides is highly non-trivial Query interpretation, optimizing Queries stay constant across host languages Many points of entry Germ of OO: modularize
M.P. Johnson, DBMS, Stern/NYU, Spring Impedance mismatch problem Big problem, though: impedance mismatch Data structures in our app-programming lang. don’t automatically map onto those in SQL Different types/representations for data In SQL: tables with scalar fields In C: scalars, records (containing records…), pointers, arrays In Java: scalars, objects, references, arrays In Perl: scalars, lists/arrays, hashes/assoc.
M.P. Johnson, DBMS, Stern/NYU, Spring SQL/host interface in embedded SQL So Q: how to transfer data between? A: Shared variables Some vars in the program can be used by SQL Prefix var with a : After query, look here for received data SQL commands embedded in app. code Identified by EXEC SQL Source code is preprocessed before regular compilation Result is (e.g.) a C program with library calls
M.P. Johnson, DBMS, Stern/NYU, Spring Programs with Embedded SQL Host language + Embedded SQL Preprocessor Host Language + function calls Host language compiler Executable Preprocessor Host language compiler Oracle’s Pro*C gcc prog.pc prog.c a.out
M.P. Johnson, DBMS, Stern/NYU, Spring Interface: SQL / Host Language Values get passed through shared variables. Colons precede shared variables in SQL statements EXEC SQL demarcates every SQL statement The variable SQLSTATE provides error messages and status reports “00000” ~ success “02000” ~ tuple not found Used in loops EXEC SQL BEGIN DECLARE SECTION; char productName[30]; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQL BEGIN DECLARE SECTION; char productName[30]; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION;
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example Context: Product (pname, price, quantity, maker) Purchase (buyer, seller, store, pname) Company (cname, city) Person(name, phone, city) Goal 1: Insert a new row in Purchase Goal 2: Look up price of product by name
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example: insert void simpleInsert() { EXEC SQL BEGIN DECLARE SECTION; char pn[20], cn[30]; /* product-name, company-name */ double p, int q; /* price, quantity */ char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; /* get values for name, price and company somehow */ EXEC SQL INSERT INTO Product(pname, price, quantity, maker) VALUES (:pn, :p, :q, :cn); } void simpleInsert() { EXEC SQL BEGIN DECLARE SECTION; char pn[20], cn[30]; /* product-name, company-name */ double p, int q; /* price, quantity */ char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; /* get values for name, price and company somehow */ EXEC SQL INSERT INTO Product(pname, price, quantity, maker) VALUES (:pn, :p, :q, :cn); }
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example: look-up int getWindowsPrice() { EXEC SQL BEGIN DECLARE SECTION; double p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = ‘Windows’; return p; } int getWindowsPrice() { EXEC SQL BEGIN DECLARE SECTION; double p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = ‘Windows’; return p; }
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example: look-up What about search for arbitrary product? Q: Will this work? int getPrice(char *name) { EXEC SQL BEGIN DECLARE SECTION; int p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = :name; return p; } int getPrice(char *name) { EXEC SQL BEGIN DECLARE SECTION; int p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = :name; return p; }
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example: look-up int getPrice(char *name) { EXEC SQL BEGIN DECLARE SECTION; char n[20]; int p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; strcpy(n, name); /* copy name to local var */ EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = :n; return p; } int getPrice(char *name) { EXEC SQL BEGIN DECLARE SECTION; char n[20]; int p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; strcpy(n, name); /* copy name to local var */ EXEC SQLSELECT price INTO :p FROM Product WHERE Product.name = :n; return p; }
M.P. Johnson, DBMS, Stern/NYU, Spring Cursors For product’s price, looked up single (scalar) value Q: What if we SELECT multiple fields? E.g., find all info for some product A: Just list destination vars separated by commas Q: What if find multiple rows? E.g., find all products above a certain price Use a cursor to step through the results Each result placed in an array Using cursors: 1. Declare the cursor 2. Open the cursor 3. Fetch tuples one by one 4. Close the cursor
M.P. Johnson, DBMS, Stern/NYU, Spring Cursor loop structure Each time around loop, we Do a FETCH to obtain next row Examine SQLSTATE to check success Can say: What is NO_MORE_TUPLES? #define NO_MORE_TUPLES !(strcmp(SQLSTATE,”02000”)) if(NO_MORE_TUPLES) break;
M.P. Johnson, DBMS, Stern/NYU, Spring Multiple-row look-up example void productToXML() { EXEC SQL BEGIN DECLARE SECTION; char pn[20], cn[30]; double p; int q; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE crs CURSOR FOR SELECT pname, price, quantity, maker FROM Product; EXEC SQL OPEN crs;... void productToXML() { EXEC SQL BEGIN DECLARE SECTION; char pn[20], cn[30]; double p; int q; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE crs CURSOR FOR SELECT pname, price, quantity, maker FROM Product; EXEC SQL OPEN crs;...
M.P. Johnson, DBMS, Stern/NYU, Spring Multiple look-up example printf(“ \n”); while (1) { EXEC SQL FETCH FROM crs INTO :n, :p, :q,:c; if (NO_MORE_TUPLES) break; printf(“ \n”); printf(“ %s \n”, n); printf(“ %d \n”, p); printf(“ %d \n”, q); printf(“ %s \n”, c); printf(“ \n”); } EXEC SQL CLOSE crs; printf(“ \n”); } printf(“ \n”); while (1) { EXEC SQL FETCH FROM crs INTO :n, :p, :q,:c; if (NO_MORE_TUPLES) break; printf(“ \n”); printf(“ %s \n”, n); printf(“ %d \n”, p); printf(“ %d \n”, q); printf(“ %s \n”, c); printf(“ \n”); } EXEC SQL CLOSE crs; printf(“ \n”); }
M.P. Johnson, DBMS, Stern/NYU, Spring More on Cursors Cursors can traverse both stored tables and queries Cursors can modify a relation as well as read it Cursors can be protected against changes to the underlying relations Can determine the order in which the cursor will get tuples by the ORDER BY keyword in the SQL query The cursor can be a scrolling one: can go forward, backward +n, -n, Abs(n), Abs(-n)
M.P. Johnson, DBMS, Stern/NYU, Spring Cursor on query not table EXEC SQL DECLARE c CURSOR FOR SELECT beer, price FROM Sells WHERE bar = ‘Izzy''s'; EXEC SQL OPEN CURSOR c; while(1) { EXEC SQL FETCH c INTO :theBeer, :thePrice; if (NOT FOUND) break; /* format and print beer and price */ } EXEC SQL CLOSE CURSOR c; EXEC SQL DECLARE c CURSOR FOR SELECT beer, price FROM Sells WHERE bar = ‘Izzy''s'; EXEC SQL OPEN CURSOR c; while(1) { EXEC SQL FETCH c INTO :theBeer, :thePrice; if (NOT FOUND) break; /* format and print beer and price */ } EXEC SQL CLOSE CURSOR c;
M.P. Johnson, DBMS, Stern/NYU, Spring Modifications with cursors As we traverse through result set, can modify the current row Can also modify with arb. WHERE clauses NB: In regular SQL, usually modify sets of rows (UPDATE WHERE …) With cursors, we update the last row fetched Simple example: in RentStab table, we decide we want to raise (e.g., by 5%) all our prices Unless price > 2000, in which case they’re deleted
M.P. Johnson, DBMS, Stern/NYU, Spring Modification by cursor example void raisePrices() { EXEC SQL BEGIN DECLARE SECTION; double p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE crs CURSOR FOR SELECT price FROM RentStab; EXEC SQL OPEN crs;... void raisePrices() { EXEC SQL BEGIN DECLARE SECTION; double p; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE crs CURSOR FOR SELECT price FROM RentStab; EXEC SQL OPEN crs;...
M.P. Johnson, DBMS, Stern/NYU, Spring Modification by cursor example while (1) { EXEC SQL FETCH FROM crs INTO :p; if (NO_MORE_TUPLES) break; if (p < 2000) EXEC SQL UPDATE RentStab SET price = 1.05*price; WHERE CURRENT OF RentStab; else EXEC SQL DELETE FROM RentStab WHERE CURRENT OF RentStab; } EXEC SQL CLOSE crs; } while (1) { EXEC SQL FETCH FROM crs INTO :p; if (NO_MORE_TUPLES) break; if (p < 2000) EXEC SQL UPDATE RentStab SET price = 1.05*price; WHERE CURRENT OF RentStab; else EXEC SQL DELETE FROM RentStab WHERE CURRENT OF RentStab; } EXEC SQL CLOSE crs; }
M.P. Johnson, DBMS, Stern/NYU, Spring NYU Infrastructure MySQL is on sales Command shell: mysql User: NetID Pass: University ID number Server: mysql2 The Oracle client is now on sales Command shell: sqlplus User: NetID Pass: first & last initials & last 3 digits of the University ID number
M.P. Johnson, DBMS, Stern/NYU, Spring Pro*C e.g. Example script: sample1.pc See Pro*C tutorialPro*C tutorial Pro*C compiler is proc Must include /oracle/precomp/public Must link with shared library /oracle/lib/libclntsh.so Includes makefile proc.mk, but may require modifications sales% cp /oracle/precomp/demo/proc/sample1.pc. // change user/pass, fully qualify emp sales% proc sample1.pc sales% gcc -osample1 -I/oracle/precomp/public /oracle/lib/libclntsh.so sample1.c sales% sample1 sales% cp /oracle/precomp/demo/proc/sample1.pc. // change user/pass, fully qualify emp sales% proc sample1.pc sales% gcc -osample1 -I/oracle/precomp/public /oracle/lib/libclntsh.so sample1.c sales% sample1
M.P. Johnson, DBMS, Stern/NYU, Spring Embedded SQL example Example script: sample2.pc See Pro*C tutorialPro*C tutorial Goal: display all salespeople Use cursor to scroll through results sales% cp /oracle/precomp/demo/proc/sample2.pc. sales% proc sample2.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample2 sample2.c sales% sample2 sales% cp /oracle/precomp/demo/proc/sample2.pc. sales% proc sample2.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample2 sample2.c sales% sample2
M.P. Johnson, DBMS, Stern/NYU, Spring Limitation of embedded SQL Okay for apps with a fixed set of queries/updates Maybe very simple kiosks But consider, say, sqlplus or the sqlzoo website Processes arbitrary queries from user Can we do this with embedded SQL?
M.P. Johnson, DBMS, Stern/NYU, Spring Dynamic SQL In dynamic SQL, query string can be taken as a parameter, passed to DB Two steps: Prepare: compiles/optimizes the string Execute: executes the query Combine together: EXECUTE IMMEDIATE But separate if query is executed many times (why?)
M.P. Johnson, DBMS, Stern/NYU, Spring Dynamic SQL myquery = a SQL variable not prefixed by : void runQuery() { EXEC SQL BEGIN DECLARE SECTION; char *command; EXEC SQL END DECLARE SECTION; /* command set to some query string */ EXEC SQL PREPARE myquery FROM :command; EXEC SQL EXECUTE myquery; /* or just: */ EXEC SQL EXECUTE IMMEDIATE :command; } void runQuery() { EXEC SQL BEGIN DECLARE SECTION; char *command; EXEC SQL END DECLARE SECTION; /* command set to some query string */ EXEC SQL PREPARE myquery FROM :command; EXEC SQL EXECUTE myquery; /* or just: */ EXEC SQL EXECUTE IMMEDIATE :command; }
M.P. Johnson, DBMS, Stern/NYU, Spring Dynamic SQL example Example script: sample8.pc See Pro*C tutorialPro*C tutorial Goal: find employees from department 10 Start with query as string sales% cp /oracle/precomp/demo/proc/sample8.pc. sales% proc sample8.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample8 sample8.c sales% sample8 sales% cp /oracle/precomp/demo/proc/sample8.pc. sales% proc sample8.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample8 sample8.c sales% sample8
M.P. Johnson, DBMS, Stern/NYU, Spring Sketch of sqlplus Something like the sqlplus program could be written as a simple dynamic SQL future lab idea? EXEC SQL BEGIN DECLARE SECTION; char query[MAX QUERY LENGTH]; EXEC SQL END DECLARE SECTION; /* issue SQL> prompt */ /* read user's text into array query */ EXEC SQL EXECUTE IMMEDIATE :query; /* go back to reissue prompt */ EXEC SQL BEGIN DECLARE SECTION; char query[MAX QUERY LENGTH]; EXEC SQL END DECLARE SECTION; /* issue SQL> prompt */ /* read user's text into array query */ EXEC SQL EXECUTE IMMEDIATE :query; /* go back to reissue prompt */
M.P. Johnson, DBMS, Stern/NYU, Spring Dynamic SQL example 2 Example script: sample10.pc See Pro*C tutorialPro*C tutorial Goal: recreate sqlplus Copy-able commands: sales% cp /oracle/precomp/demo/proc/sample10.pc. // no changes necessary sales% proc sample10.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample10 sample10.c sales% sample10 sales% cp /oracle/precomp/demo/proc/sample10.pc. // no changes necessary sales% proc sample10.pc sales% gcc -I/oracle/precomp/public /oracle/lib/libclntsh.so –osample10 sample10.c sales% sample10
M.P. Johnson, DBMS, Stern/NYU, Spring For next time Try out your Oracle accounts Next project part up soon…