|
Comments
|
Today's Top SOA Links
Product Review Dynamic SQL
Dynamic SQL
By: Bob Hendry
May. 1, 2003 12:00 AM
From the beginning, the DataWindow has been a powerful client/server control. What has set it apart from competing products is its ability to create SQL. In reality, the DataWindow is a SQL-generating machine. By keeping track of row and column statuses, the DataWindow is able to generate the correct SQL statement to UPDATE, DELETE, or INSERT rows into a database. In most instances, the developer is oblivious to the SQL generation; all that's needed to unleash all this functionality is to issue a simple update function. However, DataWindows can take SQL only so far, as their use of SQL has its limitations, for example: What many PowerBuilder developers don't know is that SQL can be executed dynamically. The level and complexity of dynamic SQL is determined by what you are trying to accomplish. At any rate, the use of dynamic SQL falls into four categories and follows a repeatable process. It's especially helpful when SQL parameters or the column set of the statements are unknown at compile time or may need to change within the runtime environment. Dynamic SQL is broken down into four formats. Dynamic SQL (Format 1) EXECUTE IMMEDIATE <SQL> USING <TRANSACTION OBJECT> The SQL statement has to be a valid string, either hard coded or a string variable. If a string variable is used, it must be bound with a colon. The Transaction object is optional and represents the database upon which this action is performed. If a Transaction object is not specified, SQLCA will be assumed. Listing 1 drops a table, re-creates it, inserts a row, then grants read permission. Note that a commit is not being performed here. If you leave database commits out of your scripts, make sure the autocommit property is set to true in the database profile of the Transaction object. Dynamic SQL (Format 2) The DynamicStagingArea is a private PowerBuilder data type used to store information about the SQL statement. Internals of this data type are hidden from the programmer. PowerBuilder gave us a default DynamicStagingArea named SQLSA. Like the PowerBuilder default Transaction object SQLCA, additional DynamicStagingAreas can be created programmatically. Using Format 2 is a two-stage process. First the DynamicStagingArea must be prepared, then its associated SQL statement can be executed. The following code prepares the DynamicStagingArea with one argument, denoted by the question mark. PowerBuilder stores this SQL information while waiting for it to be executed. The next line of code fires off the staged statement after it passes the retrieval argument. string ls_part = "Scanner" Dynamic SQL (Format 3) Listing 2 uses a cursor to read using this format and can dynamically fire off a result set into a variable list; although not demonstrated here, stored procedures can be used as well. The listing reads a list of employee last names into a ListBox. Dynamic SQL (Format 4) The DynamicDescriptionArea is a PowerBuilder data type. PowerBuilder uses a global variable of this type to hold information about the input and output arguments used in Dynamic SQL (Format 4). When the application starts, PowerBuilder creates a global DynamicDescriptionArea named SQLDA. Like the DynamicStagingArea (SQLSA), additional DynamicDescriptionAreas can be created within the code if needed. PowerBuilder provides a global DynamicDescriptionArea named SQLDA that you can use when you need a DynamicDescriptionArea variable. If necessary, you can declare and create additional object variables of the type DynamicDescriptionArea. These statements declare and create the variable, which must be done before referring to it in a dynamic SQL statement. If arguments are to be passed to the SQL statement, the SetDynamicParm function is used to fill the parameters in the input parameter descriptor array of the SQLDA before executing an OPEN or EXECUTE statement (see Listing 3). The type and value for each output parameter in SQLDA is accessed via the following functions:
The previous examples illustrated how SQL is supported outside the DataWindow technology. This next section will get back to the DataWindow and discuss how SQL can be dynamically changed. SQLPreview Event In our example, because the retrieval argument is contingent on the user, we can't define it at design time when we're creating the DataWindow. Clearly, the WHERE clause must be created dynamically. But how? We can use the four Dynamic SQL formats discussed earlier, then "push" the results into a DataWindow. A better bet would be to modify the DataWindow's SQL statement - adding a WHERE clause just before it issues a SELECT statement. The SQLPreview event is a great place to do this. Before we add code to the event, we must first determine what kind of SQL the DataWindow is planning on executing. This can be determined by using the following enumerated data types. Their meanings are intuitive so I won't elaborate on them:
SQLSyntax is especially helpful to us. Since it contains the current SQL to be executed, we can "intercept" it and change/append as needed. When we're finished tweaking it, we call the SetSQLPreview function. This function passes our SQL statement to the DataWindow, which then executes it (see Listing 4). When a new SQL statement is applied to a DataWindow, it overrides the one that was defined for it in the DataWindow Painter, including any retrieval arguments. The SetSQLPreview function should never be called outside the SQLPreview event. In addition, it should be used as close to the end of the script as possible. The SQLPreview event also has some handy return codes: If, for example, certain users were not allowed to update the database, this rule could be enforced in the SQLPreview event with the following code: If sqltype <> PreviewSelect! Then The TABLE.SELECT Property Listing 5 uses Describe and Modify to save/alter a DataWindow SQL statement. Important Note About the Describe Function SetSQLSelect Function The main limitation of the SetSQLSelect statement is that it can only be used for DataWindows that have a SQL SELECT data source, and there can be no retrieval arguments defined within the DataWindow. A good example of when to use SetSQLSelect is when small changes need to made to a WHERE clause. For example, if we needed to look up all employees who lived in "MA," and, if none existed, look up all employees who live in "CA": string ls_cur_sql Why TABLE.SELECT is Preferred over SetSQLSelect In addition to the SELECT property, other important TABLE properties exist. It's worth it to take a peek. Dynamic DataWindows
1. The DataWindow control must exist at runtime. When we talk about dynamic DataWindows, we're talking about the object and not the control. 2. The dynamic DataWindow object that we create cannot be saved. Its scope is limited to the instance of the window. 3. The SQL is valid - in this example we are assuming that the user-entered SQL is well formed and correct. Listing 6 uses two important functions. The following are the SyntaxFromSQL and Create functions, and the arguments they accept. SyntaxFromSQL Create If all goes well, the DataWindow object will be created and the user will see it as the contents on the DataWindow control. At this point you can use Describe and Modify as you would on any other DataWindow. Final Thoughts Reader Feedback: Page 1 of 1
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
|||||||||||||||||||||||||||