12.07.2015 Views

Module 13 (Introduction to SQL - Part 2).pdf

Module 13 (Introduction to SQL - Part 2).pdf

Module 13 (Introduction to SQL - Part 2).pdf

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Whirlwind Tour of <strong>SQL</strong>, <strong>Part</strong> 2Web and Database ProgrammingMichael LynchCopyright © 2005-2009 by Michael F. Lynch Ph.D.


What We Will Cover – <strong>Part</strong> 2Aggregation queriesJOIN clausesRelationships among tablesTypes of JOIN clausesCombining JOINs and QualifiersSELECT INTO statementsINSERT statementsDELETE and UPDATE statements


AGGREGATE FUNCTIONS


Aggregate FunctionsThere is a special class of functions calledaggregate functions, so named becausethey operate across groups (or aggregations)of records.


Aggregate FunctionsConsider this construct:SELECT Sum(Salary) AS [Total Salary]FROM Employees;This asks for a summation function <strong>to</strong> be run on the fieldSalary for all the records in the Table Employees.This query will return a single row with a single field. Thefield will be named “Total Salary” and it will containthe actual dollar amount which is the sum of all theSalary fields in all the records in the Employees table.


Aggregate FunctionsSELECT Sum(Salary) AS [Total Salary]FROM Employees;Note that the result of the Sum(Salary)expression is given the name “TotalSalary”. Otherwise the DB Engineassigns a name for us. AS is good <strong>to</strong> use!


Aggregate FunctionsSince the name we assigned has a space in it, weneed <strong>to</strong> put the name inside of the square brackets.This is a Microsoft rule, not an official <strong>SQL</strong> rule.Other dialects of <strong>SQL</strong> support something similar(like using double quotes).In general, you are allowed <strong>to</strong> name fields andquery calculations with names that have spaces inthem. However, you will then need <strong>to</strong> useadditional punctuation, like the square brackets inMicrosoft Access or <strong>SQL</strong> Server, or very likelyquote marks in other database products.


Best PracticeIn general, I recommend against usingembedded spaces in field names, because ofthe maintenance headaches it introduces.You might be able <strong>to</strong> make a case for usingembedded spaces if you know in advancethat non-technical people will be runningqueries using <strong>to</strong>ols like Query-By-Example(QBE), in which case the names may beregarded as more user friendly.


Aggregate FunctionsIn general, you cannot combine regularfield lists and calculations in a SELECTquery without adding additional qualifiers.This SELECT query results in an error:SELECT LastName, FirstName, Sum(Salary)AS [Total Salary] FROM EmployeesWhy?


Aggregate FunctionsThe LastName, FirstName fields try <strong>to</strong> requestindividual records, while the Sum(Salary)expression tries <strong>to</strong> request a single calculationover all the records. Both cannot be true.This, however, is legal:SELECT Sum(Salary) AS [Total Salary],Avg(Salary) AS [Average Salary]FROM Employees


Aggregate FunctionsFunction UseApplies ToSum Total of the values in a field. Numbers, Dates, Money, Au<strong>to</strong> NumberAvg Average of the values in a field. Numbers, Dates, Money, Au<strong>to</strong> NumberMin Lowest value in a field. Text, Numbers, Dates, Money, Au<strong>to</strong>NumberMax Highest value in a field. Text, Numbers, Dates, Money, Au<strong>to</strong>NumberCount Number of values in a field, Text, Memo, Numbers, Dates, Money,(not counting Null values).Yes/No, Au<strong>to</strong>Number, OLE ObjectStDev Standard deviation of the values Numbers, Dates, Money, Au<strong>to</strong>Numberin a field.Var Variance of the values in a field. Numbers, Dates, Money, Au<strong>to</strong>Number


Aggregate FunctionsHere is an example of how multiple aggregatefunctions work:SELECT Sum(Salary) AS [Total Salary],Avg(Salary) AS [Average Salary], Min(Salary) AS[Min Salary], Max(Salary) AS [Max Salary],Count(Salary) AS [Num Employees], StDev(Salary)AS [Std Dev], Var(Salary) AS Variance FROMEmployeesAlthough convoluted, this is a legal <strong>SQL</strong> sentenceand should execute correctly without complaint.


Aggregate FunctionsIf all we could do was run aggregate functionsonly over the entire set of records, they would notbe very useful.<strong>SQL</strong> provides two keywords, GROUP BY andHAVING, which give us much better control overhow the aggregate functions are <strong>to</strong> be applied.Queries that need <strong>to</strong> return both aggregatefunctions and ordinary column (field) values aresometimes called vec<strong>to</strong>r aggregates. These use theGROUP BY clause.


Aggregate FunctionsFor this type of query, the aggregate functions arespecified as usual (often with AS phrases <strong>to</strong> give aname <strong>to</strong> the results), and one or more ordinarycolumns (fields) are specified as well. Theordinary columns must then also appear in theGROUP BY clause.SELECT Cus<strong>to</strong>merID, Count (OrderID) ASOrderCount FROM OrdersGROUP BY Cus<strong>to</strong>merID


Aggregate FunctionsYou do not have <strong>to</strong> list any ordinary columns inthe list after the SELECT keyword for the query <strong>to</strong>work, but if you don’t then what comes back willprobably be difficult <strong>to</strong> interpret.We do not have <strong>to</strong> limit ourselves <strong>to</strong> only oneordinary column. We can “nest” our grouping byspecifying more than one column, and creating anappropriate grouping in the GROUP BY clause.


GroupingThese two queries retrieve the same information,but the way the information is returned <strong>to</strong> us willbe different:SELECT Cus<strong>to</strong>merID, ShipVia, Count (OrderID)AS OrderCount FROM OrdersGROUP BY ShipVia, Cus<strong>to</strong>merIDSELECT Cus<strong>to</strong>merID, ShipVia, Count (OrderID)AS OrderCount FROM OrdersGROUP BY Cus<strong>to</strong>merID, ShipVia


GroupingIn the first query, the summary records returnedwill be grouped by ShipVia first (stronger sort),then by Cus<strong>to</strong>merID (weaker sort).In the second query, the summary records returnedwill be grouped by Cus<strong>to</strong>merID first, then byShipVia.Which one <strong>to</strong> use entirely depends on what useyou wish <strong>to</strong> make of the returned data.


GroupingThe HAVING clause operates very much like a WHEREclause, but can only be used with a GROUP BY construct.SELECT Cus<strong>to</strong>merID, ShipVia, Count(OrderID)AS OrderCount FROM OrdersGROUP BY Cus<strong>to</strong>merID, ShipVia HAVING ShipVia>1This query will limit the ShipVia <strong>to</strong> shippers 2 and 3 (bothare greater than 1 but not equal <strong>to</strong> 1). After that, the GROUPBY clause creates the remainder of the report. Notice howthe HAVING clause works like a WHERE clause, but only withaggregation queries.


GroupingIncidentally, the above is not the bestexample, as we could simply have used aWHERE clause directly.However, when using JOINs (which wehave not seen yet), being able <strong>to</strong> specify aHAVING clause becomes important.


GroupingHere is an example that uses a WHERE clause anda GROUP BY clause:SELECT Cus<strong>to</strong>merID, ShipVia, Count(OrderID)AS OrderCount FROM OrdersWHERE Freight > 10.00GROUP BY Cus<strong>to</strong>merID, ShipViaHere, the WHERE clause explicitly subsets onlythose records where Freight > 10.00. TheGROUP BY and aggregation counts work off onlythat subset of records.


JOIN CLAUSES


The JOIN ClauseThe JOIN clause is the means by whichtwo (or more) tables (or queries) can becombined and treated as a unit.Joins are how the power of the relationaldatabase model is expressed. By usingthem you exploit the interrelationshipsamong sets of items (the tables) and theitems themselves (the records).


The JOIN ClauseJoins usually make use of the keys that havebeen established in the tables that you areworking with.In essence, the key from one table ismatched <strong>to</strong> one or more keys having thesame value in another table so that allrelated items can be retrieved from two (ormore) tables.


The JOIN ClauseAlthough I am using the term “tables” here, youcan actually write SELECT (and other kinds ofqueries) with a JOIN that can reference not onlythe tables in your database, but other queries youhad already written.Thus, ever more complex relationships can beexpressed by creating cascading sets of queriesthat reference other existing queries, and so forth.


Design StrategiesThis is generally a good strategy <strong>to</strong> follow whenbuilding complex systems.Begin by creating the more elementary and morecentral queries, then weave these in<strong>to</strong> largerqueries that do more elaborate things.Definitely consider placing these in S<strong>to</strong>redProcedures once you have them working.Also, Access is handy as a pro<strong>to</strong>typing <strong>to</strong>ol, evenif it doesn’t scale well for real-world use. You caneven import it in<strong>to</strong> <strong>SQL</strong> Server.


The JOIN ClauseTo retrieve joined data from two or more tables,the tables must first share a meaningfulrelationship. The tables <strong>to</strong> be joined must possessa column or columns that share a common set ofvalues that allow the tables <strong>to</strong> be meaningfullinked.The common column(s) are called the join key orcommon key.


The JOIN ClauseThe join key or common key will often be thenatural key of the tables involved.For example, the field EmployeeID in thesituation where we join Employees withEmployeeTraining.It is highly unusual for there <strong>to</strong> be more than onekey that can tie <strong>to</strong>gether a given pair of tables. Ifyou are seeing that in your design, you areprobably doing something wrong.


The JOIN ClauseHere is an example of a simple JOIN thatwe can use in the NorthWind database:SELECT *FROM Employees INNER JOIN OrdersON Employees.EmployeeID =Orders.EmployeeIDNote that only EmployeeID makes sense as thekey that links Orders with Employees.


The JOIN ClauseThe above query will systematically match up therecords from both the Employees and theOrders tables, using the join key rules given inthe ON clause.That is, as the database engine runs through theEmployees table, it simultaneously obtains allthe order records that that employee was involvedin placing (where the EmployeeID field of theOrders table agreed with the EmployeeID of theEmployees table).


The JOIN ClauseThus, for each employee record, there maybe a large number of order records matched<strong>to</strong> it, and all of these are returned.Of course, since we haven’t added anyadditional qualifiers, and since we used theasterisk in the SELECT clause, the resultingrecordset has a fair amount of redundancy.


Speeding Things UpWe could have written the above <strong>SQL</strong> morecompactly, like this:SELECT *FROM Employees E INNER JOIN Orders OON E.EmployeeID = O.EmployeeIDThis syntax lets us assign temporary (andshort) names <strong>to</strong> tables that can be used asabbreviations in all subsequent references.


Relationships Among Tables


Relationships among TablesThe way we use JOINs can be classified asone of the following:• One-<strong>to</strong>-One• One-<strong>to</strong>-Many• Many-<strong>to</strong>-Many


One-To-OneOne-<strong>to</strong>-One: A record from the left-hand table isexpected <strong>to</strong> match exactly one record from theright-hand table. This is how we would do“vertical partitions”.Except for vertical partition situations (forexample, where we might keep information forwidespread access about an employee (like nameand department) in one table, and privateinformation in another (like salary and SSN), theone-<strong>to</strong>-one situation is relatively rare.


One-To-ManyOne-<strong>to</strong>-Many: The most likely type. A recordfrom the left-hand table is expected <strong>to</strong> matchpossibly zero, one, or a large number of recordsfrom the right-hand table.In the North Wind example, each order would beexpected <strong>to</strong> have at least one [Order Details]record associated with it. Each record in the[Order Details] table references one “lineitem” of a product placed for an order.


Many-To-ManyMany-<strong>to</strong>-Many: this is the case when anynumber of records from the left-hand table areexpected <strong>to</strong> match any number of records from theright-hand table.This would be the case if we were <strong>to</strong> matchProducts with [Order Details]. Any givenproduct could be expected <strong>to</strong> appear in manydifferent order “line items” (details), and similarly,any given order might reference a large number ofdifferent products.


Showing RelationshipsIn the query wizard and other places inAccess, the relationships are expressed forus using the little numeral “1” and/or theinfinity sign as needed.Many-<strong>to</strong>-Many relationships also have aspecial purpose in data normalization,where we make use of an additional table(which I often call a “glue table”) <strong>to</strong> makethese associations.


Showing RelationshipsHere is a relationships picture for the North Wind database:


Showing RelationshipsNotice this relationships between Employees, Ordersand Cus<strong>to</strong>mers:The 1 - ∞ from Employees <strong>to</strong>Orders plus the ∞ - 1 fromOrders <strong>to</strong> Cus<strong>to</strong>mersimplies that Employees has amany-<strong>to</strong>-many relationshipwith Cus<strong>to</strong>mers , throughOrders. Orders acts as theGlue Table here.


Showing RelationshipsThe above implies that Employees doindeed have a many-<strong>to</strong>-many relationshipwith Cus<strong>to</strong>mers.This makes sense: Any employee is able <strong>to</strong>place orders for any number of cus<strong>to</strong>mers,and any cus<strong>to</strong>mer can have its order placedvia any employee.


TYPES OF JOIN CLAUSES


The JOIN ClauseThere are five types of JOINs that you canspecify:• INNER JOIN• LEFT (OUTER) JOIN• RIGHT (OUTER) JOIN• FULL JOIN• CROSS JOIN


The INNER JOINThis is the default type of join (if you don’tspecify the “INNER”), and probably themost widely used type.The INNER JOIN specifies thatunmatched rows in either table are <strong>to</strong> beomitted in the recordset that is returned(Note that they are not deleted from theoriginal tables; they are simply not includedin the requested recordset.)


The INNER JOINConsider this example:SELECT *FROM Employees INNER JOIN OrdersON Employees.EmployeeID =Orders.EmployeeID


The INNER JOINIn the above example, any employee who had zeroorders attributed <strong>to</strong> him or her would be left out ofthe recordset.Similarly, any orders that had an EmployeeIDthat could not be found in the Employees tablewould be left out of the recordset as well.Of course, the latter condition is probably an error.Every order should have a valid EmployeeID.


The INNER JOINThis brings up a design issue:Typically, when designing things likeEmployees table, we probably will never want<strong>to</strong> delete an employee record, <strong>to</strong> prevent this sor<strong>to</strong>f thing from happening.Instead, we might a Boolean field calledCurrentEmployee and a Date/Time fieldcalled TerminationDate <strong>to</strong> indicate when anemployee left the company.


The LEFT JOINThe LEFT JOIN specifies that all records fromthe left-hand table be returned, even if the recordhas no matching records in the right-hand table.If we used a LEFT JOIN in the previousexample, all Employee records would be returned,even employees who generated no Orders.In such a case, the employee record who had zeroothers would be returned exactly once, and thefields that came from the right-hand table wouldbe NULL in that record.


The LEFT JOINThis is not necessarily an error. It isperfectly reasonable for some employees —those not involved in Sales — <strong>to</strong> not haveany orders attributed <strong>to</strong> them.Note that if we use a LEFT JOIN (or aRIGHT JOIN for that matter), we have <strong>to</strong>pay attention <strong>to</strong> which table we put on theleft and on the right.


The RIGHT JOINThe RIGHT JOIN specifies that all records fromthe right-hand table be returned, even if the recordhas no matching records in the left-hand table.If we had used a RIGHT JOIN in the previousexample, all Order records would be returned,even those with unmatched EmployeeID fields.Any order record which could not be matched <strong>to</strong>any employee would be returned exactly once, andthe fields that came from the left-hand table(Employees) would be NULL in that record.


The RIGHT JOINAs with the LEFT JOIN, we have <strong>to</strong> payattention <strong>to</strong> which table we put on the leftand on the right.Both the LEFT and RIGHT JOIN arespecial cases of outer (or full) joins.


The OUTER JOINThe OUTER or FULL JOIN specifies thatall records from both tables are <strong>to</strong> bereturned, even if a record from either tablehas no matching records in the other table.Usually we want <strong>to</strong> control how this worksa little more closely than that. So weusually explicitly say LEFT JOIN orRIGHT JOIN, so that we can leave out therecords that we are not interested in.


The OUTER JOINHad we used an OUTER JOIN in theprevious example, a “superset” of all recordsthat could be formed from Employees andOrders would be returned.This set might include employees whogenerated no orders, and orders that couldnot be matched <strong>to</strong> any employee.


The OUTER JOINThis means possibly getting NULL fields ineither the Employees portion of the recordor the Orders portion of the record, whichwill generally make our processing moredifficult <strong>to</strong> do.If we use an OUTER JOIN, we really don’thave <strong>to</strong> worry about the sequence that thetables appear in.


The OUTER JOINAs a matter of good database designpractice, you should avoid outer joins asmuch as possible, because of the addedcomplexity and extra code needed <strong>to</strong> handlethe resulting special cases.Try instead <strong>to</strong> use left joins consistently,always expressing the query so that theselection of the left-hand table makes sense.


The CROSS JOINThis is a very odd type of join. In a cross join,every record from the left-hand table is matched <strong>to</strong>every record from the right-hand table, in amultiplicative way. The resulting recordset can behuge (that is, m × n records).Thus, if we had 500 employees and 40000 ordersin our database (and didn’t use any WHERE clause<strong>to</strong> limit our selection), a CROSS JOIN wouldreturn 500 x 40000 = 20,000,000 records!


The CROSS JOINWhy would we ever want <strong>to</strong> use this?It turns out that this is useful for a type ofstatistical analysis called the cross-tab(hence the name).


The CROSS JOINHowever, when running a cross-tab analysis, wesharply limit the size of the resulting recordset by(1) only asking for the fields we really need for theanalysis,(2) using WHERE clauses (<strong>to</strong> restrict recordselection <strong>to</strong> only the items we really need), and(3) using a lot of aggregate functions (<strong>to</strong> computesummary values over many records). Aggregatefunctions greatly reduce the resulting recordcount.


COMBINING JOINS ANDQUALIFIERS


Using JOIN and WHEREOf course, we can also use the WHEREclause in combination with JOIN clauses <strong>to</strong>really home in on the records we want.


Using JOIN and WHEREIf, for example, we want <strong>to</strong> find out order his<strong>to</strong>ryfor only those employees who earn $50,000+/year,we can add it in a WHERE clause:SELECT *FROM Employees E INNER JOIN Orders OON E.EmployeeID = O.EmployeeIDWHERE Employees.Salary >= 50000


Using JOIN and ORDER BYWe can also use the ORDER BY clause incombination with JOIN clauses <strong>to</strong> force theresulting record set <strong>to</strong> be sorted by whateverfields we want.The fields that participate in the sort can befrom either table.


Using JOIN and WHEREIf, for example, we want <strong>to</strong> find out order his<strong>to</strong>ryfor only those employees earning $50,000/year,we can add this in the WHERE clause:SELECT *FROM Employees E INNER JOIN Orders OON E.EmployeeID = O.EmployeeIDWHERE E.Salary >= 50000ORDER BY E.Salary, O.Cus<strong>to</strong>merID


Using JOIN and WHEREHere, the sort order would first show theemployees in ascending salary amount(which each set of orders grouped withinthem), then, within the orders for eachemployee, the orders would themselves beordered by the Cus<strong>to</strong>merID who placedthe order.


Compound JoinsFinally, we can “cascade” our joins <strong>to</strong>combine three or more tables.We do this by first setting up pairs of joins,then in turn join their results.The <strong>SQL</strong> can get a little messy, so usingau<strong>to</strong>matic <strong>to</strong>ols like QueryBuilder in Accesshelps a lot.


Compound JoinsFinal ResultsResults from joining A and BJOINJOINResults from joining C and DJOINTable A Table B Table C Table D


Northwind ExampleSELECT DISTINCTROWCategories.CategoryName,Products.ProductName,Sum(CCur([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100) AS ProductSalesFROM(Categories INNER JOIN ProductsON Categories.CategoryID = Products.CategoryID)INNER JOIN(Orders INNER JOIN [Order Details]ON Orders.OrderID = [Order Details].OrderID)ON Products.ProductID = [Order Details].ProductIDWHERE (((Orders.ShippedDate) Between #1/1/94# And #12/31/94#))GROUP BY Categories.CategoryName, Products.ProductName;


Compound JoinsThis example produces a report of productsales, organized first by category(beverages, etc.), then by product.It shows the <strong>to</strong>tal dollar amount for eachproduct for 1994. Note that there are onlythree fields that will appear in the finalQuery: CategoryName, ProductNameand ProductSales


Compound JoinsThe calculation for computing the line item([Order Details]) pricing is the same oneused in the query called ([Order DetailsExtended]) in the original North Winddatabase.However, we want the <strong>to</strong>tal of all theseprices.


Compound JoinsThe Sum(Ccur(...)) portion is anaggregation function that computes all theactual prices for a given product (in theGROUP BY clause). We give it the handyname “ProductSales”.What is inside that Sum() function is thecalculation for computing each individualprice.


Compound JOINsAs the query computes the actual prices, theSum() function forces them <strong>to</strong> be groupedby ProductName (which is what we want<strong>to</strong> see in the report).Further, we want the products themselvesgrouped by category. This is what the twoelements in the GROUP BY clause are for.


Compound JOINsIn the JOIN section, the first half does thejoining between Products andCategories. The second half does thejoining between Orders and [OrderDetails].Finally these two sub-joins are, in effect,combined in<strong>to</strong> a grand join that attaches thedollar values <strong>to</strong> the Products (as sorted byCategory).


OTHER KINDS OF JOINS


The Self JOINThis is used <strong>to</strong> join a table… <strong>to</strong> itself.Seems strange, but ideal for the kind of situationin the Employees table <strong>to</strong> retrieve who themanagers of employees are:SELECT E.FirstName, E.LastName,EMgr.FirstName AS MgrFirstName,EMgr.LastName AS MgrLastName FROMEmployees E INNER JOIN Employees EMgrON E.ReportsTo = EMgr.EmployeeID


Non-Equi JOINsSo far, we’ve used only the equal sign in the ONclause of our joins, but we don’t have <strong>to</strong>.This statement will pair up all employees againstall other employees (for example, <strong>to</strong> schedule theFriday night LAN party deathmatch):SELECT E1.FirstName, E1.LastName,E2.FirstName, E2.LastName FROMEmployees E1 INNER JOIN Employees E2ON E1.EmployeeID E2.EmployeeID


Non-Equi JOINsBut this will give us exactly twice as manyrecords as it should (since A B meansthe same thing as B A).Fix is <strong>to</strong> just use a strict less-than (or strictgreater-than) and it will come out right.In general, you can build more elaboratetest conditions in the ON clause, but usecare!


More About Subqueries


SubqueriesThis is a powerful technique, introducedearlier for the IN clause example.You can use an entire chunk of SELECTstatement (called the subquery) whereverregular data is expected.Where you can do this depends on the waythis subquery returns data.


SubqueriesThere are three possibilities. The subquerycan return:• One column and one row (a scalar)• One column with multiple rows• Multiple columns with multiple rowsWhich one it is determines where you canuse it.


SubqueriesThis example involves using a subqueryinside an IN clause. It can work with asingle column with one or more rows.SELECT * FROM Companies WHERE CountryIN (SELECT CountryName FROMWorldCountries WHERE Continent ='Europe')


SubqueriesThis example involves using two subqueriesinside a BETWEEN clause. In this instance eachsubquery has <strong>to</strong> return exactly one row and onecolumn (a scalar):SELECT * FROM Employees WHERE SalaryBETWEEN (SELECT Min(Salary) FROMSalaryPolicy WHERE JobCat=‘Programmer')AND (SELECT Max(Salary) FROMSalaryPolicy WHERE JobCat=‘Programmer')


SubqueriesThe third example, involving a subquerythat produces multiple columns withmultiple rows will be shown shortly.Check out Chapter 9 in the “Learning <strong>SQL</strong>”book on Safari Online for more aboutsubqueries.


SELECT … INTO STATEMENTS


SELECT … INTO StatementsEverything shown in the foregoing slides,no matter how complex, can have its results(in effect) poured in<strong>to</strong> a new table using theSELECT … INTO construction.SELECT fieldlist INTO tablenameWHERE etc. etc. etc.


SELECT … INTO StatementsPut the name of a new table you would like<strong>to</strong> have created immediate after the INTOkeyword.Follow it with whatever WHERE, JOIN, etc.clauses you need <strong>to</strong> get the outcome youdesire.


SELECT … INTO StatementsThe list of fields you supply after theSELECT keyword will cause thecorresponding fields <strong>to</strong> appear in theresulting new table.This is a good place <strong>to</strong> use the AS keyworda lot.


SELECT … INTO StatementsUsing SELECT…INTO can be useful in thecontext of data mining, but it does generatethe need for more s<strong>to</strong>rage and alsopropagates redundant data all over the place.Better <strong>to</strong> use the View mechanism (assumingyou’re using a “real” database).


INSERT STATEMENTS


Changing DataAbsolutely everything involving SELECTstatements is supposed <strong>to</strong> be passive. Nomatter what sort of SELECT statement yourun, it should never affect the data in theunderlying tables.We will now cover statements that DOaffect the data in the underlying tables.


The INSERT VerbThe easiest way <strong>to</strong> add new data <strong>to</strong> a table iswith an INSERT statement. You will dothis a lot from within Active Server Pages.Essentially, what you do is build up anINSERT statement by string concatenationfrom the data values you collect. Whenfinished, you execute the INSERTstatement and the data goes in<strong>to</strong> the table.


The INSERT VerbThe format for the INSERT statement is:INTO is optionalINSERT INTO tablename(list_of_fields)VALUES (list_of_values)


The INSERT VerbWhere:• tablename is the name of the table in<strong>to</strong>which the data are inserted,• list_of_fields is a “comma separated”list of all the field names for which you aresupplying values, and• list_of_values is a “comma separated”list of all the corresponding values.


INSERT ExampleHere is how <strong>to</strong> insert a record in<strong>to</strong> the Orderstable of North Wind:INSERT INTO Orders (Cus<strong>to</strong>merID,EmployeeID, OrderDate, RequiredDate,ShipVia, Freight, ShipName,ShipAddress, ShipCity, ShipRegion,ShipPostalCode, ShipCountry)VALUES ('BLAUS', 8, Now, Now+30, 2,10.95, 'Johann Schmitt', '123Bierstrasse', 'Berlin', ' ', 'ABC-123','Germany')


INSERT ExampleEvery value given in the VALUES sectioncorresponds item-for-item with the fieldname given earlier. “BLAUS” becomes theCus<strong>to</strong>merID, 8 becomes theEmployeeID, and so forth.By the way, the above query actually worksin MS Access.


INSERT ExampleIf we examine the design of the Orderstable, we will discover that we have notspecified a value for every field.For example, we did not list the field,OrderID, nor did we specify a value for it.OrderID is an “au<strong>to</strong>increment” type fieldin the Orders table, and the database —not us — assigns it a value.


INSERT ExampleAlso note that we neither listed nor assigned avalue <strong>to</strong> ShippedDate, since we don’t know thevalue for that field yet.Had ShippedDate been a required field, thiswould have created a problem. We might havehad <strong>to</strong> fake-up some special date value that wecould always check for later (e.g. 1/1/1900).This sort of special value is sometimes called asentinel value.


INSERT ExampleWe also had <strong>to</strong> use a string containing asingle blank for ShipRegion. Accesscomplains if an empty string is used (tryit!).This is because “Allow Zero String” is set<strong>to</strong> false in the database design.


The INSERT VerbBecause it is so useful <strong>to</strong> be able <strong>to</strong> doINSERT INTO programmatically inside ofcode where no GUI developmentenvironment exists (as with ASP pages), itis OK <strong>to</strong> write large boiler-plated INSERTqueries that do the work for us.It is better practice, however, <strong>to</strong> do this sor<strong>to</strong>f thing inside a s<strong>to</strong>red procedure, if yourdatabase supports s<strong>to</strong>red procedures.


One ApproachFirst collect the new data from the user as as resul<strong>to</strong>f the user filling in a CGI-based form.With that data, build up the above INSERT querypiece by piece by concatenating all the data items(as strings) the user entered in.• The StringBuilder class may be more convenient for this.Once the string is ready, pass it <strong>to</strong> the appropriatedatabase component <strong>to</strong> cause this record <strong>to</strong> beinserted in<strong>to</strong> the desired table.


A Better ApproachOr… put the code for the INSERT queryinside a s<strong>to</strong>red procedure and call that fromyour program instead (we will see this whenwe return <strong>to</strong> ADO.NET).This s<strong>to</strong>red procedure needs <strong>to</strong> take asparameters all the data you intend <strong>to</strong> insert.Then pass that information as parameters <strong>to</strong>the s<strong>to</strong>red procedure call.


Notes About INSERTThe table that you are inserting in<strong>to</strong> mustalready exist and have the same field namesas the fields that your query will begenerating.You can omit the list of fields al<strong>to</strong>gether ifyou take pains <strong>to</strong> supply a set of VALUES inthe order that precisely matches the table’ssequence of fields.


Notes About INSERTThere are usually other ways <strong>to</strong> insert records in<strong>to</strong>tables that don’t involve INSERT INTOconstructions (like the old DAO interface).These “native” database components often executefaster, since they bypass the need <strong>to</strong> parse the <strong>SQL</strong><strong>to</strong> trigger the resulting actions underneath.But especially in Client/Server programming, andfor greatest generality, the INSERT INTOcommand, while slower, is easier <strong>to</strong> write andmaintain than more native, and non-portable,programming alternatives.


Notes about INSERTWe can use NULL if we have <strong>to</strong>, providedthe corresponding field permits NULL.Any calculation that results in a value thatwould be legal if given directly can be usedin place of a regularly specified value.


Notes about INSERTDEFAULT can be used if the enginesupports it and there was a default valueactually designated in the original designfor the corresponding field.This is the best way <strong>to</strong> handle insertingdefault values in<strong>to</strong> fields that are otherwiseregarded as “required”.


OTHER ACTION STATEMENTS


The DELETE VerbThe DELETE verb is a simple and dangerous <strong>SQL</strong>command.You can wipe out large chunks of data with it, sobe careful. Most databases do not support the ideaof UNDO, so you would need <strong>to</strong> res<strong>to</strong>re the datafrom some backup s<strong>to</strong>rage if you jumped the gun.You will nearly always want <strong>to</strong> carefully qualifythe items you want <strong>to</strong> delete with an appropriateWHERE clause.


The DELETE VerbHere is a simple and dangerous DELETEstatement:DELETE * FROM OrdersOf course, if you’ve applied referential integritytechniques when designing the database, youprobably won’t able <strong>to</strong> get away with the abovecommand, since it has common key relationshipswith other tables and the delete won’t go forward.


The DELETE VerbHere is one that might make more sense:DELETE * FROM Orders WHERE OrderDateBetween #1-Jan-93# AND #31-Dec-93#In general, about the only time you want <strong>to</strong> deleteall records in a table is when you have been usinga temporary table as a scratchpad of some sort, orif you’ve already made an archival backup and cannow get rid of main data.


The DELETE VerbAs we have seen, the primary qualifier in aDELETE statement is the WHERE clause.Of course, since the target of the WHEREclause follows the same syntax as theWHERE clause in an ordinary SELECTstatement, the rules for selecting the records<strong>to</strong> be deleted can be as elaborate as youneed.


The DELETE VerbOften, you should give carefulconsideration as <strong>to</strong> whether a DELETEstatement is the most appropriate way <strong>to</strong>handle the removal of data.This comes up when dealing with notionslike employees. It is nearly alwaysincorrect <strong>to</strong> simply delete employees froman Employees table.


Notes About the DELETE VerbEven if the employee dies or is fired, there is a lo<strong>to</strong>f other information that must be kept around evenif the physical employee isn’t:• tax, health, and regula<strong>to</strong>ry compliance information• data about work the employee did and so forth, whichwould be become difficult <strong>to</strong> reconstruct if thecorresponding employee record were removed.Instead, consider a field like CurrentStatus <strong>to</strong>contain information about the actual employmentstate of the employee.


The UPDATE VerbThe UPDATE command allows you <strong>to</strong>change the value of a field or fields in somesystematic way on all the selected records a<strong>to</strong>nce.Since the UPDATE command can changedata in records, possible quite a lot of them,this <strong>to</strong>o is a potentially dangerouscommand.


UPDATE ExampleHere is a simple example (although there isprobably not much of a reason why youwould want <strong>to</strong> bump all the dates in thetable <strong>to</strong> a year later):UPDATE Orders SET OrderDate =OrderDate + 365


UPDATE ExampleThis one might make more sense. Say ourNorth Wind Supplier #27 (EscargotsNouveaux) were suddenly able <strong>to</strong> deliversome items that had previously had beenunavailable. We could say:UPDATE ProductsSET Discontinued = FalseWHERE SupplierID = 27


UPDATE ExampleIf you wanted <strong>to</strong> raise prices by 10%, youcould say:UPDATE Products SETUnitPrice = UnitPrice * 1.10


UPDATE ExampleOf course this might lead <strong>to</strong> messy numbers. We reallywant <strong>to</strong> make sure we don’t get prices like $18.4533.Since we can write arithmetic expressions inside <strong>SQL</strong>, wecan fix it <strong>to</strong> something like this:UPDATE Products SET UnitPrice = CLng((UnitPrice * 110)) /100Try the math out <strong>to</strong> convince yourself that this sort of trickactually works!


TRANSACTIONS


<strong>SQL</strong> TransactionsA critically important consideration whenattempting <strong>to</strong> perform a series of related actions onmore than one table or query is guaranteeing thatall actions get completed correctly.The classic example of this is in “double entrybookkeeping”, the basic principle by which allmodern accounting systems are constructed.In double entry bookkeeping, debits and creditsmust always be kept in exact balance. Always!


<strong>SQL</strong> TransactionsIf $100.00 is taken out of a checking account <strong>to</strong>pay a credit card bill, of which $65.00 dollars ofthat was used <strong>to</strong> entertain a client at a restaurantand $35.00 of that was <strong>to</strong> buy nuts and bolts at thehardware s<strong>to</strong>re, we would need <strong>to</strong>…• remove $100.00 of money from the Cash account(which, in the curious world of accounting requirescrediting cash);• debit the Entertainment Expense account by $65.00;• debit the Hardware Expense account by $35.00.


<strong>SQL</strong> TransactionsIt would be disastrous if we completed thecredit side of our transaction but could notcomplete the debit side, or vise versa. Weneed a way of guaranteeing the integrity ofthe entire transaction.Curiously, it’s called the TRANSACTIONstatement.


<strong>SQL</strong> TransactionsThe basic set of steps is <strong>to</strong>…• start a transaction,• do whatever actions you need <strong>to</strong> do in <strong>SQL</strong>after that,• then commit the transaction,• or else roll it back <strong>to</strong> where we were before ifsomething went wrong.


<strong>SQL</strong> TransactionsIn <strong>SQL</strong>, it might look like this:START TRANSACTION INSERT INTO Cash (transID, Amount) VALUES(12345, -100.00)INSERT INTO HardwareExp (transID, Amount)VALUES (12345, 35.00)INSERT INTO DiningExp (transID, Amount)VALUES (12345, 65.00)COMMIT TRANSACTION


<strong>SQL</strong> TransactionsThe COMMIT statement is a command <strong>to</strong> eitherperform all the <strong>SQL</strong> commands between theSTART and the COMMIT correctly, or <strong>to</strong> performnone of them.In systems like Oracle and <strong>SQL</strong> Server, there areextensive facilities for setting up transactions, andfor testing for errors and recovering from errors.A big difference between <strong>to</strong>y or demonstra<strong>to</strong>rapplications and robust commercial applications isoften found in how thoroughly this is done.


<strong>SQL</strong> TransactionsThe opposite of a COMMIT is a ROLLBACK.If, during some of that data handling, wediscovered a computation error, or, worse,the system issued an error of its own (datatable corrupted, out of drive space, servercrash, etc.), we can cleanly and reliably rollback the state of the data tables <strong>to</strong> wherethey were before we began the transaction.


Transaction ExampleSTART TRANSACTION INSERT INTO Cash (transID, Amount) VALUES (12345, -100.00)INSERT INTO HardwareExp (transID, Amount) VALUES (12345,35.00)INSERT INTO DiningExp (transID, Amount) VALUES (12345,65.00)--- Problem detected! ---ROLLBACK TRANSACTION


CONCLUSIONS


ConclusionsThis has been a fairly thorough review ofwhat you can do with <strong>SQL</strong>, but it does notexhaust the <strong>to</strong>pic.The Learning <strong>SQL</strong> book will give youmore basic information, while the <strong>SQL</strong>Cookbook can show you a number ofrather stranger (yet very powerful)techniques you can use.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!