Question: How do I create a table that can contain only a single row for each connection, and that row exists only as long as that connection exists, and is visible only on that connection?
Answer: Start with a non-shared CREATE GLOBAL TEMPORARY TABLE statement to ensure that rows inserted by each connection are only visible on that connection and are automatically deleted when the connection finishes.
Then, use a CHECK constraint to ensure that each connection can insert only one row.
Here's an example of a connection settings table; "non-shared" is the default when the SHARE BY ALL clause is omitted:
CREATE GLOBAL TEMPORARY TABLE connection_settings ( one_row_per_connection INTEGER NOT NULL DEFAULT 1 CHECK ( one_row_per_connection = 1 ), setting1 INTEGER NOT NULL DEFAULT 0, setting2 VARCHAR ( 100 ) NOT NULL DEFAULT '', setting3 VARCHAR ( 1 ) NOT NULL DEFAULT 'Y', PRIMARY KEY ( one_row_per_connection ) ) NOT TRANSACTIONAL;
The schema for a GLOBAL TEMPORARY TABLE is permanent and visible to all connections; in other words, you CREATE it once and then use it on each connection.
Each row of data, however, is temporary in the sense that it lasts no longer than the connection that inserted it, and each row is only visible to code running on the connection that inserted it.
Note: The rules that "data is temporary" and "only visible" do not apply when the SHARE BY ALL clause is used; see the Help for more information about non-shared versus shared global temporary tables.The CHECK ( one_row_per_connection = 1 ) constraint enforces the "single row for each connection" requirement by limiting the primary key to a single value... since primary keys must be unique, that implies there can only be one row.
Tip: Don't forget to code NOT TRANSACTIONAL or ON COMMIT PRESERVE ROWS on all your GLOBAL TEMPORARY TABLE statements... unless you want your data in those tables to disappear every time you run a COMMIT. The default is ON COMMIT DELETE ROWS, one of those rare decisions that violates the rule "Watcom does things the way they should be done."The resulting table is somewhat similar to connection-level variables created with the CREATE VARIABLE statement:
Tip: Use the login_procedure option to ensure the row exists before the connection is used for anything else:
Table Variable Create schema when: Ahead of time On connection Create schema how: CREATE GLOBAL TEMPORARY TABLE t ... CREATE VARIABLE v... Scope of schema: All code on all connections All code on connection Data values: Multiple columns Single value Create data when: On connection On connection Create data how: INSERT t ... CREATE VARIABLE v ... Scope of data: All code on connection All code on connection Reference values how: SELECT first, then reference Direct references to variable names Update data how: UPDATE t SET c = ... SET v = ... Explicitly delete data: DELETE t DROP VARIABLE v Data implicitly deleted: End of connection End of connection
CREATE PROCEDURE DBA.connection_start() BEGIN INSERT connection_settings DEFAULT VALUES; END; SET OPTION PUBLIC.login_procedure = 'DBA.connection_start';
Warning: Don't use a Connect EVENT: a row inserted inside an event will only be visible inside that event because it runs on its own connection.
Oh, and if you're worried about overriding the default login_procedure value sp_login_environment, go read the Help to see if any of the
Here's an example of how data in the table can be used and updated:
BEGIN DECLARE @setting1 INTEGER; SELECT setting1 INTO @setting1 FROM connection_settings; END; UPDATE connection_settings SET setting2 = 'Hello, World!';
Neither the SELECT nor the UPDATE needs a WHERE clause because there's only one row.
Also, the UPDATE doesn't need a COMMIT, and it isn't affected by a ROLLBACK, because of the NOT TRANSACTIONAL clause. If you want your data to be involved in transaction processing, use ON COMMIT PRESERVE ROWS instead (or the default, ON COMMIT DELETE ROWS, if you're in that 0.01% who needs that kind of
...and if you do use ON COMMIT PRESERVE ROWS instead of NOT TRANSACTIONAL, you going to need a COMMIT when you update your table... just sayin'.
Hey, that INSERT DEFAULT VALUES clause is pretty cool, isn't it? Betcha didn't know you could do that...
No comments:
Post a Comment