function printExpensiveItems(maxPrice Price in)
tempItem Item;
open expensiveItems for tempItem with
#sql{
select
EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE,
EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
from EGL.ITEM
where
EGL.ITEM.PRICE >= :maxPrice
order by
EGL.ITEM.ITEM_ID asc
};
forEach (tempItem)
SysLib.writeStdout(tempItem.Name :: " " ::
tempItem.Description :: " $" :: tempItem.Price);
end
What if you wanted to return items that had a price less than
or equal to the parameter? Or, what if you wanted to return items between
a maximum and minimum price? Using explicit SQL in the open statement,
you would have to code three functions, one for each possibility, because
the comparisons in the WHERE clause of the SQL statement are hard-coded.selectStatement STRING = "select * from EGL.ITEM where EGL.ITEM.PRICE >= 500";Then you use the prepare statement to convert the string into an SQL statement. You must also specify a name for the statement and optionally, a record variable to indicate which SQLRecord part the statement will operate on:
tempItem Item; prepare preparedStatement from selectStatement for tempItem;Then, you can use the prepared statement in place of explicit SQL in an EGL get, open, or execute statement (you will learn more about execute in a later lesson):
open expensiveItems for tempItem with preparedStatement;
tempItem Item; maxPrice Price = 500; selectStatement STRING = "select * from EGL.ITEM where EGL.ITEM.PRICE >= :maxPrice"; prepare preparedStatement from selectStatement for tempItem;In this case, the actual SQL statement will include the string :maxPrice exactly as it is, without using it as a host variable and replacing it with the value of the maxPrice variable. The result is an incorrect SQL statement.
tempItem Item; maxPrice Price = 500; selectStatement STRING = "select * from EGL.ITEM where EGL.ITEM.PRICE >= " :: maxPrice; prepare preparedStatement from selectStatement for tempItem;In this case, the value of the maxPrice variable is resolved when EGL creates the string, creating the following SQL statement:
select * from EGL.ITEM where EGL.ITEM.PRICE >= 500Later in this lesson, you will learn an alternate way of using variables in prepared statements.
incorrectSQL STRING; incorrectSQL = "select * from EGL.ITEM where"; incorrectSQL ::= "EGL.ITEM.PRICE >= :maxPrice"; incorrectSQL ::= "order by EGL.ITEM.PRICE";This example creates the following incorrect SQL statement:
select * from EGL.ITEM whereEGL.ITEM.PRICE >= :maxPriceorder by EGL.ITEM.PRICEThis statement needs a space after WHERE and another before ORDER BY.
Also, prepared SQL statements, like explicit SQL, must be appropriate for the EGL statement with which they are used. For example, the EGL get and open statements expect a result set. To use a prepared statement with either of these statements, the SQL code must return a result set. For this reason, you cannot prepare an SQL INSERT or DELETE statement and then use that statement with get or open.
Completed query: select * from EGL.ITEM where EGL.ITEM.PRICE between 50.00 and 500.00 order by EGL.ITEM.PRICE Serial Mouse Great little mouse. All kinds'a applications. $65.22 Keyboard Got QWERTY? If not, go get this awesome flat keyboard. $78.99 Watch Keep time - and look rakish! $99.01 Shredder Don't let that politically-sensitive document fall into the wrong hands! $198.99 Combination Safe Keep your valuables safe and secure. Put 'em in here. $222.22You can edit the parameter values and try different ranges, including null values, as in this example:
function main()
minPrice, maxPrice Price?;
minPrice = 500;
maxPrice = null;
try
printItemRange(minPrice, maxPrice);
onException(exception SQLException)
handleDBException(exception);
end
end
Passing values of 500 and null yields results like these:Completed query: select * from EGL.ITEM where EGL.ITEM.PRICE >= 500.00 order by EGL.ITEM.PRICE Desktop PC Lots'a power, at the right price. Includes monitor. $888.55 Laptop PC Great little machine. Take it anywhere with you. $1111.11
Here is the complete code of the selectItems.egl file. If you see any errors marked by red X symbols in the file, make sure your code matches the code in this file:Completed selectItems.egl file after lesson 4A.
selectStatement STRING = "select * from EGL.ITEM where "; ... selectStatement ::= "EGL.ITEM.PRICE between " :: minPrice :: " and " :: maxPrice :: " ";When you create a prepared statement, you can also place question marks (?) into the statement, indicating that the values will be filled in later:
selectStatement2 STRING = "select * from EGL.ITEM where " :: "EGL.ITEM.PRICE between ? and ? " :: "order by EGL.ITEM.PRICE"; tempItem Item; prepare preparedStatement2 from selectStatement2 for tempItem;Now the prepared statement has places for two host variables, represented by the question marks in the BETWEEN clause. When you are ready to use the prepared statement, insert values with the using statement. For example, to search for rows with a price between 5 and 500, pass the literals 5 and 500 to the statement:
open expensiveItems2 for tempItem with preparedStatement2 using 5, 500;Of course, you can also use variables along with the using keyword:
open expensiveItems2 for tempItem with preparedStatement2 using minPrice, maxPrice;
function printRanges()
tempItem Item;
selectStatement string = "select * from EGL.ITEM where " ::
"EGL.ITEM.PRICE between ? and ? " ::
"order by EGL.ITEM.PRICE";
prepare preparedStatement from selectStatement for tempItem;
SysLib.writeStdout("\nPrinting values between 0 and 200");
open expensiveItems for tempItem with preparedStatement using 0, 200;
forEach(tempItem)
SysLib.writeStdout(tempItem.Name :: " " :: tempItem.Description ::
" $" :: tempItem.Price);
end
SysLib.writeStdout("\nPrinting values between 200 and 500");
open expensiveItems for tempItem with preparedStatement using 200, 500;
forEach(tempItem)
SysLib.writeStdout(tempItem.Name :: " " :: tempItem.Description ::
" $" :: tempItem.Price);
end
SysLib.writeStdout("\nPrinting values between 500 and 1,000");
open expensiveItems for tempItem with preparedStatement
using 500, 1000;
forEach(tempItem)
SysLib.writeStdout(tempItem.Name :: " " :: tempItem.Description ::
" $" :: tempItem.Price);
end
end
Using host variables in this way, it's possible to rewrite the program from the previous section to use a single prepared statement, instead of altering the statement for each possible case: