A quick peek at what passing a table as a parameter really means? This example uses the D4 language of Dataphor, MS Sql Server 2005, the Orders and OrderDetails tables from the Northwind db. Consider the following two simple sql queries which use a group by column and return the maximum value of a column for each group. select top 5 EmployeeID,Max(Freight) as MaxFrt from Orders group by EmployeeID order by MaxFrt EmployeeID MaxFrt ----------- --------------------- 6 367.6300 8 398.3600 1 544.0800 4 719.7800 9 754.2600 select top 5 ProductID,Max(UnitPrice) as MaxUP from OrderDetails group by ProductID order by MaxUP ProductID MaxUP ----------- --------------------- 33 2.5000 24 4.5000 13 6.0000 52 7.0000 54 7.4500 We can put each query in a stored procedure and return all the rows. create procedure OrdersMaxFrt as select EmployeeID,Max(Freight) as MaxFrt from Orders group by EmployeeID create procedure OrderDetailsMaxUP as select ProductID,Max(UnitPrice) as MaxUP from OrderDetails group by ProductID Given that the queries concern themselves with 2 mutually exclusive sets of facts (tables) what can be said of any similarities between them? It's clear they perform the same general operation, they both group the data by a single column and return a max of single column. So they return rows consisting of two columns. We can say (loosely speaking) each sp returns a table. What's left? Look at the columns of each query: SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Orders' TABLE_NAME COLUMN_NAME DATA_TYPE ---------- ----------- --------- Orders EmployeeID int Orders Freight money Orders OrderID int SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'OrderDetails' TABLE_NAME COLUMN_NAME DATA_TYPE ------------ ----------- --------- OrderDetails OrderID int OrderDetails ProductID int OrderDetails UnitPrice money Each query uses a group by column of int(eger) and a max of a money column. Each query returns a table of an int column and a money. Each table involves a column (OrderID) of int in the primary key definition. All these similarities can be seen as 'structural' similarities. And when we talk of such similarities we are talking the language of 'type' just as we would say the number 5 is an int type. But in this context we are speaking of 'table' type. We can now take all these structural ideas and create a D4 procedure that performs the group by operation on a table that is passed as a parameter. create operator GetaMax(aTable:table{aPkCol:Integer,aGroupCol:Integer,aMoneyCol:Money}): table{aGroupCol:Integer,aMax:Money} begin result:= aTable group by{aGroupCol} add {Max(aMoneyCol) aMax}; end; The operand (argument) aTable is a table defined in terms of its column name and corresponding data type: table{aPkCol:Integer,aGroupCol:Integer,aMoneyCol:Money} The procedure returns a result which is also a table: table{aGroupCol:Integer,aMax:Money} And now we can answer the question of what passing a table as a parameter really means. It just means the definition of the table in terms of its structure, its column names and their data type. By contrast, the only reference to a table in sql is by its name. The structural use of table information in sql does not exist. In other words, there is no table 'type' in sql and therefore nothing on which a table parameter could be based on. In sql there is only the literal representation of a table (its name) whereas in D4 it can be represented as a variable. It is the same difference representing the literal string 'ABC' but not being able to assign 'ABC' to a variable of type string. (Note how sql tries to overcome the lack of a table type: dynamic sql ☻ .) Ok, now to how the D4 GetaMax procedure works. The sql stored procedure exec OrdersMaxFrt becomes: select GetaMax(Orders {OrderID aPkCol,EmployeeID aGroupCol,Freight aMoneyCol}) {aGroupCol EmployeeID,aMax MaxFrt} order by {EmployeeID}; EmployeeID MaxFrt ---------- --------- 1 $544.08 2 $810.05 3 $1,007.64 4 $719.78 5 $890.78 6 $367.63 7 $830.75 8 $398.36 9 $754.26 In D4 the: 'GetaMax(Orders {OrderID aPkCol,EmployeeID aGroupCol,Freight aMoneyCol})' means execute the GetaMax operator using the Orders table but renaming the Orders columns to the table type (the columns with their data types) declared in the operator. In renaming the columns and because the columns have the same corresponding data types as declared in the operator we succeed in passing the Orders table (as a variable). So the EmployeeID (int) column is renamed to aGroupCol and Freight (money) to aMoneyCol (same for OrderID). The '{aGroupCol EmployeeID,aMax MaxFrt}' simply renames the generic columns of the operator back to the meaningful column names of the Orders table. Likewise, The sql stored procedure exec OrderDetailsMaxUP becomes: select GetaMax(OrderDetails {OrderID aPkCol,ProductID aGroupCol,UnitPrice aMoneyCol}) {aGroupCol ProductID,aMax MaxUP} order by {ProductID}; ProductID MaxUP --------- ------- 1 $18.00 2 $19.00 3 $10.00 4 $22.00 . Just as a variable defined as int can take an infinite number of values the GetaMax procedure represents the same operation on a possibly infinite number of tables. As I hope you can imagine the concept of a table type/argument has far reaching implications for application development. Finally, if you have Dataphor you can run the following two batches to compare the GetaMax operator to the sql stored procedures. (Note that the D4 operator 'SQLQuery' is used for pass-thru queries sending t-sql directly to Sql Server. Also Sql Server converts the max of a money type to decimal. To make the comparision with GetaMax it must be converted back to money). //Check Orders. var Compare_the_Tables:='The 2 tables are different'; if ( GetaMax(Orders {OrderID aPkCol,EmployeeID aGroupCol,Freight aMoneyCol}) {aGroupCol EmployeeID, aMax MaxFrt} ) = (SQLQuery('exec OrdersMaxFrt') {EmployeeID,ToMoney(MaxFrt) MaxFrt}) then Compare_the_Tables:='The 2 tables are the same'; select Compare_the_Tables; //The 2 tables are the same //Check OrderDetails. var Compare_the_Tables:='The 2 tables are different'; if ( GetaMax(OrderDetails {OrderID aPkCol,ProductID aGroupCol,UnitPrice aMoneyCol}) {aGroupCol ProductID,aMax MaxUP} ) = (SQLQuery('exec OrderDetailsMaxUP') {ProductID,ToMoney(MaxUP) MaxUP}) then Compare_the_Tables:='The 2 tables are the same'; select Compare_the_Tables; //The 2 tables are the same bye for now, steve
Dataphor SQL RAC (Relational Application Companion)
A site of hope for those looking for a true relational database system
- a one-one requirement constraint with dataphor (1)
- anatomy of sql server part I - what is a stored procedure (1)
- anatomy of sql server part II - the unit test as part of the database (1)
- anatomy of sql server part III - what does deferred name resolution really mean (1)
- censoring sql posts (1)
- creating an opposite constraint in dataphor (1)
- dataphor (2)
- Dataphor (7)
- dataphor # 13 a table as a parameter (1)
- dataphor - download and start working with it (1)
- dataphor - fixed sized word segments (1)
- dataphor # 10 sql mythology (1)
- dataphor # 11 string differences (1)
- dataphor # 12 trimming a string (1)
- dataphor # 14 sql the meaning of Update..From (1)
- dataphor # 15 views with substance (1)
- dataphor # 16 inclusive vs exclusive solutions (1)
- dataphor # 17 a visual look at ranking queries (1)
- dataphor # 18 data scrubbing using lists (1)
- dataphor # 19 create intervals over strings (1)
- dataphor # 20 browsing an sql window (1)
- dataphor # 21 an example of relational division (1)
- dataphor # 22 reusable procedures (1)
- dataphor # 23 repley to Michel (1)
- dataphor # 24 basics of the table type (1)
- dataphor # 25 extending the dense rank function (1)
- dataphor # 26 query a hierarchy with explode (1)
- dataphor # 27 combine strings with Split and Concat (1)
- dataphor # 28 constants and variables or sql and D4 (1)
- dataphor # 29 another example of relational division (1)
- dataphor #1 introduction (1)
- dataphor #2 splitting strings (1)
- dataphor #3 string concatenation (1)
- dataphor #4 comment (1)
- dataphor #5 comment (1)
- dataphor #6 formal definition (1)
- dataphor #7 sql: table this (1)
- dataphor #8 list to table (1)
- dataphor #9 table constraints (1)
- dataphor creating lists in a query (1)
- extracting numbers from a string with dataphor (1)
- jeff modens dynamic crosstabs for sql server (1)
- linq to sql the what and why (1)
- linq to sql as a window of opportunity to sql users (1)
- linq to sql should be important to sql users (1)
- linq to sql vs. older 4GL attempts (1)
- listing missing table item (1)
- Multiple cascade paths to the same table (1)
- RAC (4)
- RAC #1 comment (1)
- RAC #2 example (1)
- RAC #3 finding the Nth number in a string (1)
- RAC #4 Sql Server 2005 ranking functions vs. Rac ranking (1)
- sorting a delimited string by its numerical string parts (1)
- sql an example of extreme implicit conversions (1)
- sql can't handle complicated cascading updates (1)
- sql CTE should be a variable not a value (1)
- sql dense rank for identifying consecutive runs (1)
- sql is there really a table variable (1)
- sql ranking functions explained by relational types (1)
- sql server triggers are best set based (1)
- sql the idea of using substring to simulate lists (1)
- sql the undefined trigger in Sql Server (1)
- sql vs relational on tables (1)
- sql what the sql CTE covers up (1)
- types and procedures (1)
Showing posts with label dataphor # 13 a table as a parameter. Show all posts
Showing posts with label dataphor # 13 a table as a parameter. Show all posts
Wednesday, June 13, 2007
Dataphor - Passing a table as a parameter
Subscribe to:
Posts (Atom)
