Database Forum / DB2 Topics / April 2006
How to do...well...anything...in DB2 SQL
|
|
Thread rating:  |
Ian Boyd - 07 Mar 2006 16:39 GMT i've been thrown into a pit with DB2 and have to start writing things such as tables, indexes, stored procedures, triggers, etc. The online reference is only so helpful. The two pdf manuals are only so helpful. Googling is only so helpful.
So let's start with some simple SQL constructs, that i know so very well in SQL Server, that seem to be like pulling teeth in DB2.
1. Selecting a value
SQL Server: SELECT 'Hello, world!' (1 row(s) affected)
DB2: SELECT 'Hello, world!' Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "LECT 'Hello, world!'". Expected tokens may include: "<table_expr>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
SELECT 'Hello, world!' FROM SYSIBM.SysDummy1 1 Row(s) affected
Is there a SysDummy2? 3? Why?
1. Declaring a variable
SQL Server: DECLARE @SavedUserID int The command(s) completed successfully.
DB2: DECLARE SavedUserID integer; Error: SQL0104N An unexpected token "integer" was found following " DECLARE SavedUserID". Expected tokens may include: "END-OF-STATEMENT". LINE NUMBER=1. SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
2. Setting a variable SQL Server: DECLARE @ProcessID int SET @ProcessID = @spid or SET @SavedUserID = (SELECT User_ID FROM Connection_Users WHERE spid = @@spid) or (depricated) SELECT @SavedUseID = UserID FROM Connection_Users WHERE spid = @@spid
DB2: DECLARE ApplicationID varchar(128) --can't declare variables SET ApplicationID = Application_ID() or DECLARE ApplicationID varchar(128) --can't declare variables SET ApplicationID = (SELECT APPLICATION_ID() FROM SYSIBM.SYSDUMMY1);
3. Returning a value SQL Server: SELECT @@spid AS ProcessID or DECLARE @ProcessID int SET @ProcessID = @spid SELECT @ProcessID
DB2 SELECT Application_ID() Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "ect application_ID()". Expected tokens may include: "<table_expr>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) or SELECT Application_ID() FROM IBM.SysDummy1 --SysDummy2 or DECLARE ApplicationID varchar(128) --can't declare variables SET ApplicationID = (SELECT APPLICATION_ID() FROM SYSIBM.SYSDUMMY1); SELECT ApplicationID
3. Returning rows from a stored procedure SQL Server CREATE PROCEDURE foo AS SELECT @@spid AS ProcessID
DB2 CREATE PROCEDURE foo DYNAMIC RESULT SETS 1 LANGUAGE SQL P1: BEGIN --declare the cursor DECLARE cursor1 CURSOR WITH RETURN FOR SELECT Application_ID() FROM SYSIBM.SYSDUMMY1; -- Cursor left open for client application OPEN cursor1; END P1
Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "ROM SYSIBM.SYSDUMMY1". Expected tokens may include: "JOIN <joined_table>". LINE NUMBER=7. SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0198N The statement string of the PREPARE or EXECUTE IMMEDIATE statement is blank or empty. SQLSTATE=42617 (State:42617, Native Code: FFFFFF3A) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END P1". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
And finally, the full trigger i'm trying to create in DB2 that i can't can't make work.
CREATE TRIGGER SUPERDUDE.LI_DAILYLOGS --"LI_DAILYLOGS" = "LogInsert_DailyLogs" 18 character limit in DB2 AFTER INSERT ON SUPERDUDE.DAILY_LOGS REFERENCING NEW_TABLE AS INSERTED FOR EACH STATEMENT MODE DB2SQL BEGIN ATOMIC -- Load the saved UserID DECLARE SavedUserID integer;
SELECT SavedUserID = User_ID FROM Connection_Users WHERE Application_ID = Application_ID();
INSERT INTO Audit_Log( ChangeDate, RowID, ChangeType, -- Username, HostName, AppName, UserID, TableName, FieldName, TagID, Tag, OldValue, NewValue) SELECT getdate(), i.Daily_Log_ID, 'INSERTED', -- USER_NAME(), HOST_NAME(), APP_NAME(), SavedUserID, 'Daily_Logs', --TableName '', --FieldName NULL, --TagID i.Name, --Tag '', --OldValue '' --NewValue FROM Inserted i; END;
Error: SQL0104N An unexpected token "integer" was found following " DECLARE SavedUserID". Expected tokens may include: "END-OF-STATEMENT". LINE NUMBER=10. SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "=" was found following "SELECT SavedUserID ". Expected tokens may include: "<space>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0204N "SUPERDUDE.INSERTED" is an undefined name. SQLSTATE=42704 (State:42704, Native Code: FFFFFF34) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
Brian Tkatch - 07 Mar 2006 17:12 GMT >So let's start with some simple SQL constructs, that i know so very well in >SQL Server, that seem to be like pulling teeth in DB2. Though i agree that DB2 can be tedious and confusing, note that SQL Server is super easy, and it pretty much breaks the standard to do it. So, give db2 a shot. :) As long as you come with the attitude that it can be done, you just don't know how, the users of this group are very helpful.
>1. Selecting a value SQL Server: SELECT 'Hello, world!'
This is wholly incorrect. It is not SQL whatsoever. It is a convenience added by Sybase/SQL Server.
In the DB2 world, you use: VALUES 'Hello World'
> SELECT 'Hello, world!' FROM SYSIBM.SysDummy1 > 1 Row(s) affected > >Is there a SysDummy2? 3? Why? Compatability with other systems, that do not use a special statement, and require *all* statments to include a TABLE reference. Oracle supplies a one-record TABLE called Dual. Other systems use other names.
>1. Declaring a variable > >SQL Server: > DECLARE @SavedUserID int > The command(s) completed successfully. Drop the useless @ symbol, and end all statement with a semi-colon. Also, there is no implicit block of code, so you must start your own.
BEGIN DECLARE SaverUserID INT; END
>3. Returning a value >SQL Server: [quoted text clipped - 3 lines] > SET @ProcessID = @spid > SELECT @ProcessID Again, use VALUES.
>3. Returning rows from a stored procedure >SQL Server > CREATE PROCEDURE foo AS > SELECT @@spid AS ProcessID
>DB2 > CREATE PROCEDURE foo [quoted text clipped - 7 lines] > OPEN cursor1; > END P1 db2 => create function application_id() returns int return 1 DB20000I The SQL command completed successfully. db2 => CREATE PROCEDURE foo \ db2 (cont.) => DYNAMIC RESULT SETS 1 \ db2 (cont.) => LANGUAGE SQL \ db2 (cont.) => P1: BEGIN \ db2 (cont.) => --declare the cursor \ db2 (cont.) => DECLARE cursor1 CURSOR WITH RETURN FOR \ db2 (cont.) => SELECT Application_ID() FROM SYSIBM.SYSDUMMY1; \ db2 (cont.) => -- Cursor left open for client application \ db2 (cont.) => OPEN cursor1; \ db2 (cont.) => END P1 DB20000I The SQL command completed successfully.
Works for me. :)
>And finally, the full trigger i'm trying to create in DB2 that i can't can't >make work. I have little experience with TRIGGERs in DB2. I'll leave that to someone else. :)
B.
Ian Boyd - 07 Mar 2006 19:02 GMT 1. Selecting a value
SQL Server:
> SELECT 'Hello, world!' > In the DB2 world, you use: > VALUES 'Hello World' How about aliasing field names?
> SELECT 'Hello, world!' AS MyLovelyWelcomeMessage i try:
> VALUES 'Hello, world!' AS MyLovelyWelcomeMes Error: SQL0104N An unexpected token "AS" was found following "LUES 'Hello, world!'". Expected tokens may include: "INTO". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
i assume that i should be using a SELECT, and not VALUES
> SELECT 'Hello, world!' AS MyLovelyWelcomeMessage FROM SYSIBM.SysDummy1 2. Declaring Variables
> BEGIN > DECLARE SaverUserID INT; > END Doesn't work for me: Error: SQL0104N An unexpected token "DECLARE" was found following "BEGIN ". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
i throught that the field type in DB2-SQL was INTEGER. No?
Really scary when i can't get 3 lines to work. So i try:
> DECLARE SaverUserID INT; And now i can't even get one line to work. (Yes, frustrating) Error: SQL0104N An unexpected token "INT" was found following "DECLARE SaverUserID". Expected tokens may include: "END-OF-STATEMENT". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
3. Returning a value SQL Server:
>> SELECT @@spid AS ProcessID >> or [quoted text clipped - 3 lines] > > Again, use VALUES. Again, i assume that VALUES is a bad thing:
> VALUES Application_ID() AS ProcessID Error: SQL0104N An unexpected token "AS" was found following "UES Application_ID()". Expected tokens may include: "->". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
And that i really should be using SELECT
> SELECT Application_ID() AS ApplicationID FROM SYSIBM.SysDummy1 which does work, but i'd really like to know how to declare variables, set variables and return variables. So i try:
>BEGIN > DECLARE ApplicationID varchar(128); [quoted text clipped - 5 lines] > SELECT ApplicationID AS ApplicationID FROM SYSIBM.SysDummy1; >END Error: SQL0104N An unexpected token "BEGIN DECLARE ApplicationID varchar" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "<values>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "END" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "<update>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "END BEGIN" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "<space>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
So i'm pretty much stuck. Three lines, and i can't any one work. Note the heavy use of BEGIN/END because "there is no implicit block of code, so you must start your own." Surely that can't be the syntax i have to use. i would have thought that the following would have been enough, but i can't really tell since i get the errors:
>BEGIN > DECLARE ApplicationID varchar(128); > SET ApplicationID = VALUES Application_ID(); > SELECT ApplicationID AS ApplicationID > FROM SYSIBM.SysDummy1; >END Error: SQL0104N An unexpected token "BEGIN DECLARE ApplicationID varchar" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "<values>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "SET ApplicationID =" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "<space>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0206N "APPLICATIONID" is not valid in the context where it is used. SQLSTATE=42703 (State:S0022, Native Code: FFFFFF32) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
3. Returning rows from a stored procedure
>DB2 > CREATE PROCEDURE foo [quoted text clipped - 8 lines] > END P1 > Works for me. :) Any idea why it doesn't work for me? Any idea what the error message is trying to say: Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "ROM SYSIBM.SYSDUMMY1". Expected tokens may include: "JOIN <joined_table>". LINE NUMBER=7. SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0198N The statement string of the PREPARE or EXECUTE IMMEDIATE statement is blank or empty. SQLSTATE=42617 (State:42617, Native Code: FFFFFF3A) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END P1". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
Complaining about me ending my statement after the SELECT, that that it is expecting a JOIN. Should be joining to something. Do i need to also join to a dummy table? e.g.
>CREATE PROCEDURE foo > DYNAMIC RESULT SETS 1 [quoted text clipped - 5 lines] > OPEN cursor1; >END P1 No, that doesn't work:
Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "IBM.SYSDUMMY1 ON (1=1)". Expected tokens may include: "<psm_semicolon>". LINE NUMBER=7. SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "OPEN cursor1". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98) Error: SQL0104N An unexpected token "END-OF-STATEMENT" was found following "END P1". Expected tokens may include: "JOIN <joined_table>". SQLSTATE=42601 (State:42601, Native Code: FFFFFF98)
>>And finally, the full trigger i'm trying to create in DB2 that i can't >>make work. >I have little experience with TRIGGERs in DB2. I'll leave that to someone >else. :) That's fine, pretend it's not a trigger. Pretend it's just a regular query:
>-- Load the saved UserID >DECLARE SavedUserID integer; i can't get any variant of any variable declaration to work. Any ideas?
> SELECT SavedUserID = User_ID > FROM Connection_Users > WHERE Application_ID = Application_ID(); Is this valid DB2-SQL syntax to put a value into a variable? i can't really test it, since i cannot declare variables. Or is it invalid syntax, and i should be using:
> SET SavedUserID = SELECT User_ID > FROM Connection_Users > WHERE Application_ID = Application_ID(); or should i be using VALUES along the lines of:
> SET SavedUserID = VALUES Application_ID; i guess, which is preferred? Again, i can't test anything, because i cannot declare variables.
> INSERT INTO Audit_Log( > ChangeDate, [quoted text clipped - 21 lines] > '' --NewValue > FROM Inserted i; (NOTE: Anyone who knows T-SQL will recognize getdate(), USER_NAME(), HOST_NAME(), APP_NAME(). i assume that DB2-SQL has some built-in function to get the current date/time. i also assume DB2-SQL has no built-in function to get the current Username, MachineName or AppName)
Aside from the SQL syntax stuck in there (because i can't get enough far enough to debug it), is that a valid syntax for doing an insert into a table in DB2 when not using VALUES?
By values i mean: INSERT INTO foo (Field1, Field2, ..., FieldN) VALUES (Value1, Value2, ..., ValueN);
Put it another way, is this a valid syntax in DB2-SQL:
> INSERT INTO foo (Field1, Field2, ..., FieldN) > SELECT Value1, Value2, ..., ValueN > FROM MyTable > WHERE ... Finally, is that the valid way to alias tables in DB2-SQL?
> FROM Inserted i will that work, or do i have to do something like:
> FROM Inserted AS i or is it some other syntax, maybe more like Java, which IBM seems to live:
> FROM (i)Inserted Finally, does DB2 support derived tables
> SELECT myo.*, MyDerivedTable.* > FROM MyTableOne mto > INNER JOIN (SELECT * FROM MyTableTwo mtt > WHERE mtt.Field4 = 'Testing') MyDerivedTable > mto.SomeJoinField = MyDerivedTable.AnotherJoinField But originally, and most importantly, what's wrong with:
DECLARE SomeNumber INT;
i think if i can get that working, i'll knock back a bottle of scotch and call today very productive. If i can get a declare working, i'll have written one line of DB2-SQL in 2 weeks of work.
Knut Stolze - 07 Mar 2006 20:14 GMT > 1. Selecting a value > [quoted text clipped - 4 lines] > > How about aliasing field names? There are no "fields" in SQL - just rows, columns and values.
>> SELECT 'Hello, world!' AS MyLovelyWelcomeMessage The question is what the column name will be good for. If you get just one row even one value, you usually don't need to name it. And if you have more, you usually have an application dealing with the data. So renamed columns are in my opinion only worthwhile for sub-queries.
> i assume that i should be using a SELECT, and not VALUES >> SELECT 'Hello, world!' AS MyLovelyWelcomeMessage FROM SYSIBM.SysDummy1 Yes, to rename a column you have to have a SELECT statement.
> 2. Declaring Variables > >> BEGIN >> DECLARE SaverUserID INT; >> END BEGIN ATOMIC DECLARE i INT; END@
> i throught that the field type in DB2-SQL was INTEGER. No? Data type.
> 3. Returning a value > SQL Server: [quoted text clipped - 7 lines] > > Again, i assume that VALUES is a bad thing: How so?
>>BEGIN >> SET ApplicationID = VALUES Application_ID(); SET ApplicationID = Application_ID();
>>END >>BEGIN >> SELECT ApplicationID AS ApplicationID FROM SYSIBM.SysDummy1; >>END Just nest this into a single statement:
VALUES application_id()
> Complaining about me ending my statement after the SELECT, that that it is > expecting a JOIN. Should be joining to something. Do i need to also join > to a dummy table? e.g. No, the join is just a suggestion telling you that how the statement _could_ continue. The problem is actually that you have a syntactically incorrect statement because the END keyword is missing.
> (NOTE: Anyone who knows T-SQL will recognize getdate(), USER_NAME(), > HOST_NAME(), APP_NAME(). i assume that DB2-SQL has some built-in function > to get the current date/time. i also assume DB2-SQL has no built-in > function to get the current Username, MachineName or AppName) Have a look at the DB2 special registers in the manual: USER, CURRENT DATE, CURRENT TIME, CURRENT TIMESTAMP.
> Aside from the SQL syntax stuck in there (because i can't get enough far > enough to debug it), is that a valid syntax for doing an insert into a [quoted text clipped - 10 lines] >> FROM MyTable >> WHERE ... Works both.
> Finally, is that the valid way to alias tables in DB2-SQL? >> FROM Inserted i > will that work, or do i have to do something like: >> FROM Inserted AS i Works both. Have a look at the syntax for the sub-select statement.
> Finally, does DB2 support derived tables > [quoted text clipped - 3 lines] >> WHERE mtt.Field4 = 'Testing') MyDerivedTable >> mto.SomeJoinField = MyDerivedTable.AnotherJoinField This are sub-queries and DB2 supports them. Have a look at the syntax diagram for queries.
> But originally, and most importantly, what's wrong with: > > DECLARE SomeNumber INT; Nothing. You just have to use it in the correct and valid context.
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Ian Boyd - 07 Mar 2006 21:15 GMT > There are no "fields" in SQL - just rows, columns and values. You channeling Celko? :)
> SELECT 'Hello, world!' AS MyLovelyWelcomeMessage > The question is what the column name will be good for. > If you get just one row even one value, you usually don't > need to name it. And if you have more, you usually have > an application dealing with the data. If there are multiple fields (a.k.a. columns) in the returned records (a.k.a. rows), and the client accesses fields (a.k.a columns) by name, then each field (a.k.a column) will need a name. Even if there is only one field (a.k.a column) in the returned records (a.k.a rows), and the client can only access fields (a.k.a columns) by name, that field (a.k.a column) will stil need a name.
> Yes, to rename a column you have to have a SELECT statement. > 2. Declaring Variables [quoted text clipped - 6 lines] > DECLARE i INT; > END@ Ah-hah! "BEGIN ATOMIC"
>> i throught that the field type in DB2-SQL was INTEGER. No? i see it now in the online help. INT is an alias for Integer field type.
3. Returning a value
>> SQL Server: >>>> SELECT @@spid AS ProcessID [quoted text clipped - 6 lines] >> Again, i assume that VALUES is a bad thing: > How so? Because rather than using VALUES:
> SET ApplicationID = VALUES Application_ID(); i don't use VALUES:
> SET ApplicationID = Application_ID(); Keep in mind that you're responding to a post i made talking to the other guy, before it was explained that VALUES constructs a virtual table.
> Have a look at the DB2 special registers in the manual: USER, CURRENT > DATE, > CURRENT TIME, CURRENT TIMESTAMP. Excellent. Thank you.
So now i'm getting closer to a compiling trigger. Next question
5. Setting a field (a.k.a column) to NULL
SQL Server
> UPDATE MyTable SET SomeField = NULL > WHERE SomeOtherField IN (SELECT KeyField FROM MyTable2 WHERE Field = 3) or
> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) > VALUES ('Ian', 'Boyd', '728 Helena', NULL, '911-426-3184') or
> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) > SELECT fname, lname, addr1, NULL, NULL FROM legacy_system In my variant of the 3rd case in DB2, it complains that "NULL is not valid in the context where it is used."
Serge Rielau - 07 Mar 2006 22:24 GMT >> There are no "fields" in SQL - just rows, columns and values. > You channeling Celko? :) *chuckle* I had the same thought. Seriously though it doesn't hurt to use the correct language. Just like it doesn't hurt to speak proper English outside the pub ;-)
>> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) >> SELECT fname, lname, addr1, NULL, NULL FROM legacy_system > > In my variant of the 3rd case in DB2, it complains that "NULL is not valid > in the context where it is used." DB2 uses strong typing. An untyped NULL (or ?) is only allowed in specific places where DB2 cann immediatly deduce the datatype. That would be UPDATE SET, SET statement and INSERT VALUES. In all other cases CAST(NULL AS <type>) will do the job. That's the way the standard is defined. No technical reason really.
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 08 Mar 2006 14:25 GMT >>> There are no "fields" in SQL - just rows, columns and values. >> You channeling Celko? :)
> *chuckle* I had the same thought. > Seriously though it doesn't hurt to use the correct language. > Just like it doesn't hurt to speak proper English outside the pub ;-) Warning. Celko bait ahead: <CelkoBait> Yes. But those are semantics of the most anal kind. i have seen many, many, many posts of Celko explaining how if you confuse a row/record and column/field, you are doing yourself a disservice.
We can all agree that someplace on my hard drive is a the value for a particular column of a particular row. And we can all agree to call that a field. Simarly, if i select a specific row from a table, that is a record.
Yes, the terms were invented when one table was stored in one file, and the notion of "the next 6 rows" was perfectly valid. Yes, modern databases store things in pages all over the place, but there is still some physical order. The btree has an order. You can't guarantee that order, or ever even see it. But the rows that you return are records.
Let us all agree that the terms record/field while originally didn't apply to RDMS's, now do. </CelkoBait>
>>> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) >>> SELECT fname, lname, addr1, NULL, NULL FROM legacy_system [quoted text clipped - 7 lines] > In all other cases CAST(NULL AS <type>) will do the job. > That's the way the standard is defined. No technical reason really. Excellent. Thank you. i, of course, would prefer it if DB2 would just do it. But i'm okay with it forcing me to tell it that what it thinks i want to do is really what i want to do.
Serge Rielau - 08 Mar 2006 15:11 GMT >>>> There are no "fields" in SQL - just rows, columns and values. >>> You channeling Celko? :) [quoted text clipped - 5 lines] > Warning. Celko bait ahead: > <CelkoBait> <snip>
> </CelkoBait> Different styles. In this group using the f-word causes a raised eyebrow. Joe i s abit more opinionated. Let me put in another way: There is a _statistical_ correlation between using the professional vocabulary and the skill level. Fields and Records are EXCEL and ACCESS speak. It _suggests_ a technologcal "redneck". In usenet, perception is everything ;-)
>>>> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) >>>> SELECT fname, lname, addr1, NULL, NULL FROM legacy_system [quoted text clipped - 10 lines] > But i'm okay with it forcing me to tell it that what it thinks i want to do > is really what i want to do. When the SQL standard was created strong typing was desired. In reality most products have long abandoned strong typing. I agree that DB2 is doing a futile "last stand" here.. one of these days that will be relaxed.
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Knut Stolze - 08 Mar 2006 07:14 GMT >> There are no "fields" in SQL - just rows, columns and values. > You channeling Celko? :) No, not really. I just want to make sure that you know the terminology used by DB2 (and the SQL standard) so that you will have an easier time when looking at the manual.
> 3. Returning a value >>> SQL Server: [quoted text clipped - 12 lines] > i don't use VALUES: >> SET ApplicationID = Application_ID(); That doesn't make VALUES a bad thing. It is just not necessary here.
> 5. Setting a field (a.k.a column) to NULL > > SQL Server >> UPDATE MyTable SET SomeField = NULL >> WHERE SomeOtherField IN (SELECT KeyField FROM MyTable2 WHERE Field = 3) Works.
> or > >> INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) >> VALUES ('Ian', 'Boyd', '728 Helena', NULL, '911-426-3184') This works too.
> or > [quoted text clipped - 3 lines] > In my variant of the 3rd case in DB2, it complains that "NULL is not valid > in the context where it is used." This does not work because NULL is untyped and DB2 does not know if the data types produced by the subselect match with the data types in the table. So try this:
INSERT INTO MyTable (Firstname, Lastname, Address, Child, Phone) SELECT fname, lname, addr1, CAST(NULL AS VARCHAR(10)), CAST(NULL AS VARCHAR(10)) FROM legacy_system
Btw, you got the error SQL0206N in this case. You should first look up the error description to correct your problem: ----------------------------------------------------------- $ db2 "? sql0206"
SQL0206N "<name>" is not valid in the context where it is used.
Explanation:
This error can occur in the following cases:
o For an INSERT or UPDATE statement, the specified column is not a column of the table, or view that was specified as the object of the insert or update.
o For a SELECT or DELETE statement, the specified column is not a column of any of the tables or views identified in a FROM clause in the statement.
o For an ORDER BY clause, the specified column is a correlated column reference in a subselect, which is not allowed.
o For a CREATE TRIGGER, CREATE METHOD or CREATE FUNCTION statement:
- The reference "<name>" does not resolve to the name of a column, local variable or transition variable.
- The condition name "<name>" specified in the SIGNAL statement has not been declared.
o For a CREATE TRIGGER statement:
- A reference is made to a column of the subject table without using an OLD or NEW correlation name.
- The left hand side of an assignment in the SET transition-variable statement in the triggered action specifies an old transition variable where only a new transition variable is supported.
o For a CREATE FUNCTION statement with a PREDICATES clause:
- The RETURN statement of the SQL function references a variable that is not a parameter or other variable that is in the scope of the RETURN statement.
- The FILTER USING clause references a variable that is not a parameter name or an expression name in the WHEN clause.
- The search target in an index exploitation rule does not match some parameter name of the function that is being created.
- A search argument in an index exploitation rule does not match either an expression name in the EXPRESSION AS clause or a parameter name of the function being created.
o For a CREATE INDEX EXTENSION statement, the RANGE THROUGH clause or the FILTER USING clause references a variable that is not a parameter name that can be used in the clause.
The statement cannot be processed.
User Response:
Verify that the names are specified correctly in the SQL statement. For a SELECT statement, ensure that all the required tables are named in the FROM clause. For a subselect in an ORDER BY clause, ensure that there are no correlated column references. If a correlation name is used for a table, verify that subsequent references use the correlation name and not the table name.
For a CREATE TRIGGER statement, ensure that only new transition variables are specified on the left hand side of assignments in the SET transition-variable statement and that any reference to columns of the subject table have a correlation name specified.
sqlcode : -206
sqlstate : 42703 -----------------------------------------------------------
Unfortunately, this particular situation is not explained explicitly. So you can only derive that NULL is interpreted as column name. (Note that DB2 allows a column to be named NULL.)
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Serge Rielau - 07 Mar 2006 20:37 GMT Ian,
(I'm consciously not quoting anything.. fresh start)
DB2 supports variables in the context of stored procedures, functions, methods, triggers and "dynamic compound statements". DB2 does not support "global variables" (and I thought SQL Server doesn't either, so I'm surprised you have an issue.
DB2 supports the SQL/PSM standard for procedural logic. To learn about this language I strongly recommend: "DB2 SQL PL" by Paul Yip et al: http://btobsearch.barnesandnoble.com/booksearch/isbninquiry.asp?btob=Y&cds2Pid=9 030&isbn=0131477005
I think the name SYSIBM.SYDUMMY1 is rooted in the fact that it returns 1 row.
The VALUES clause is actually very powerful when embedded in the from clause. E.g. instead of doing: T-SQL: SELECT * FROM (SELECT 5 UNION SELECT 6) AS X you can do: SELECT * FROM (VALUES (5), (6)) AS X.
This T-SQL: SELECT @@spid AS ProcessID is NOT column aliasing. This is a SET statement. You can either use: SET ProcessID = spid; or VALUES spid INTO processID;
Note the INTO clause. The same principle works for this T-SQL consruct: SELECT SavedUserID = User_ID FROM Connection_Users WHERE Application_ID = Application_ID();
In the SQL Standard (and thus DB2): SELECT User_ID INTO SavedUserID FROM Connection_Users WHERE Application_ID = Application_ID();
There in one difference though: while SQL Server will quietly reyurn any value if your where clause matches more than one row, DB2 will riot if more than one row is return (rightly so).
It is important to note that whenever you write a statement that contains ';' due to "substatements" you need to make sure the statement delimiter (what you know as "go" I think) is set to a value other than ';' (imagine placing 'go' after each line in a T-SQL procedure.. same confusion). With the CLP you can set the delimiter with db2 -td<character>. E.g. db2 -td@ You can also change the delimiter on the fly in CLP using --#SET TERMINATOR <character> GUIs (such as control center) typically have a preference that can be set. DB2 supports limited(!) scripting capabilities using dynamic compound (in Oracle this would be called an "anonymous block"). Again I'm surprised you try this since AFAIK SQL Server supports no such thing. all T-SQL must be in a procedure.
BEGIN ATOMIC -- Note the ATOMIC keyword! DECLARE a INTEGER DEFAULT 5; WHILE A < 5 DO SET a = a + 5; CALL proc(a); END WHILE; END
So let's move into a procedure example: db2 -t
--#SET TERMINATOR @ DROP PROCEDURE dostuff @ CREATE PROCEDURE dostuff(IN a INTEGER, INOUT b INTEGER, OUT c INTEGER) BEGIN DECLARE d INTEGER; DECLARE cur CURSOR WITH RETURN FOR SELECT TABNAME FROM SYSCAT.COLUMNS FETCH FIRST 2 ROWS ONLY; SET d = a + b; SET c = d * a; SET b = 7; OPEN cur; END @ CALL dostuff(5, 7, ?)@ --- db2 => CALL dostuff(5, 7, ?)@
Value of output parameters -------------------------- Parameter Name : B Parameter Value : 7
Parameter Name : C Parameter Value : 60
Result set 1 --------------
TABNAME ---------------------------- COLDIST COLDIST
2 record(s) selected.
Return Status = 0
OK I think that covers it. Let us know how it goes.
Cheers Serge
PS: One more thing..... the SQL/PSM standard (which is the foundation for DB2's SQL procedures) uses exception handlers for error handling. Do NOT overload them to emulate old style T-SQL. Use them just like in SQL Server 2005 Microsoft encourages you to use exception handlers.
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 07 Mar 2006 22:12 GMT > DB2 supports variables in the context of stored procedures, functions, > methods, triggers and "dynamic compound statements". > DB2 does not support "global variables" (and I thought SQL Server doesn't > either, so I'm surprised you have an issue. i don't think SQL Server has global variables either - at least i've never seen them.
> I think the name SYSIBM.SYDUMMY1 is rooted in the fact that it returns 1 > row. That's an interesting insight!
> The VALUES clause is actually very powerful when embedded in the from > clause. [quoted text clipped - 6 lines] > you can do: > SELECT * FROM (VALUES (5), (6)) AS X. i've never used any idea similar to (SELECT 5 UNION SELECT 6) AS X
i've never had a problem where i needed to join to such virtual table. Like i said before, i'll have to figure out where VALUES would be useful to me.
> This T-SQL: SELECT @@spid AS ProcessID > is NOT column aliasing. If i run this query, i get a record set with one row and one column. And that column has no name. If i want to give that column a name (or a different name) i have to use:
> SELECT @@spid AS ProcessID So the column gets renamed from "" to "ProcessID." Whereas the following SET operation
> SET ProcessID = spid; returns no rows.
> It is important to note that whenever you write a statement that contains > ';' due to "substatements" you need to make sure the statement delimiter > (what you know as "go" I think) is set to a value other than ';' (imagine > placing 'go' after each line in a T-SQL procedure.. same confusion). i've never had to use a "go" in T-SQL. All the text i submit is one batch. There is no ; needed at the end of every statement.
So now having to have not only a statement delimiter, and a batch delimiter is painful.
> Again I'm surprised you try this since AFAIK SQL Server supports no such > thing. all T-SQL must be in a procedure. No. i can send T-SQL to SQL Server and it runs it. i don't seen it to be inside a transaction or any such "BEGIN ATOMIC". It runs the SQL it is given. For example
>DECLARE @a int >SET @a = 5 >WHILE @A < 5 BEGIN > SET @a = @a + 5 > EXECUTE SomeStoredProcedure >END is perfectly valid. i can send the T-SQL to SQL Sever using it's own query tool, or using 3rd party tools, or using ADO. i give it those characters, no semicolons, no go, no begins, end, atomics; and it just runs.
> So let's move into a procedure example: Here's an interesting question. The following rus fine, exactly as is:
CREATE PROCEDURE dostuff(IN a INTEGER, INOUT b INTEGER, OUT c INTEGER) BEGIN DECLARE d INTEGER; DECLARE cur CURSOR WITH RETURN FOR SELECT TABNAME FROM SYSCAT.COLUMNS FETCH FIRST 2 ROWS ONLY; SET d = a + b; SET c = d * a; SET b = 7; OPEN cur; END
So now:
> CALL dostuff(5, 7, ?) Wrong number of parameters
> DECLARE c integer; call dostuff(5, 7, ?); An unexpected token "integer" was found following "DECLARE c ".
>BEGIN > DECLARE c integer; call dostuff(5, 7, c); >END An unexpected token "DECLARE" was found following "begin "
>BEGIN ATOMIC > DECLARE c integer; call dostuff(5, 7, c); >END The parameter mode (IN, OUT, or INOUT) is not valid for a parameter in procedure "DOSTUFF"
Why is it that the create procedure doesn't need atomic begins. It doesn't need the keyword atmoc after the begin, and it doesn't need to wrapped wholly in a begin end such as:
BEGIN ATOMIC CREATE PROCEDURE dostuff(...) BEGIN END END
But my ad-hoc sql does need atomic begins? By the way, this is far as i can get. i don't now how to fix the call to the stored procedure.
> PS: One more thing..... the SQL/PSM standard (which is the foundation for > DB2's SQL procedures) uses exception handlers for error handling. > Do NOT overload them to emulate old style T-SQL. Use them just like in SQL > Server 2005 Microsoft encourages you to use exception handlers. A welcome addition.
> OK I think that covers it. Let us know how it goes. Time to go home for the day. Day 9, nothing working yet.
Ian Boyd - 07 Mar 2006 22:46 GMT >> It is important to note that whenever you write a statement that contains >> ';' due to "substatements" you need to make sure the statement delimiter [quoted text clipped - 3 lines] > i've never had to use a "go" in T-SQL. All the text i submit is one batch. > There is no ; needed at the end of every statement. i think i see the confusion. SQL Server has no "substatements". And statements don't have to be separated by semi-colons. If i were to give the OLE DB Provider for Microsoft SQL Server the following string, as one long string (and this example is taken from the SQL Server documentation):
string myQuery = "DECLARE @MyMsg VARCHAR(50) SELECT @MyMsg = 'Hello, World.'
-- Yields an error because @MyMsg not declared in this batch. PRINT @MyMsg
SELECT @@VERSION; -- Yields an error: Must be EXEC sp_who if not first statement in -- batch. EXECUTE sp_who"
Connection.Execute(myQuery);
This will just run. The entire set of all the statments are sent over to SQL Server as one "batch", and SQL Server runs them.
Additionally, there is a standard feature built into the query tools, and that is the use of the keyword "go". It is not a T-SQL keyword, it is a word only recognized by Microsoft's query tools.
If you entered the following into Microsoft's Query Analyzer;
<quote> DECLARE @MyMsg VARCHAR(50) SELECT @MyMsg = 'Hello, World.' GO -- @MyMsg is not valid after this GO ends the batch.
-- Yields an error because @MyMsg not declared in this batch. PRINT @MyMsg GO
SELECT @@VERSION; -- Yields an error: Must be EXEC sp_who if not first statement in -- batch. sp_who </quote>
The query tool will now send 3 individual batches to SQL Server. Each batch is separate from the others. You are free to send over all the text in one batch, or you can have the tool send it over the multiple batches. But as it indicated in the example query, variables declared in one batch will no longer exist in the next batch.
So, when i'm trying to do something in DB2-SQL, e.g.:
DECLARE UserID integer SET UserID = ( SELECT application_ID() FROM sysibm.sysdummy1 ) update MyTable SET UserID = UserID WHERE UserID IS NULL delete from MyTable WHERE UserID = 3 select * from MyTable
i expect all that text to be sent to to DB2, i expect DB2 to run the query, and return me what it is supposed to return me. But DB2 doesn't just read the SQL it's given. DB2 seems to require semicolons to separate each statment. e.g.:
DECLARE UserID integer; SET UserID = ( SELECT application_ID() FROM sysibm.sysdummy1 ); update MyTable SET UserID = UserID WHERE UserID IS NULL; delete from MyTable WHERE UserID = 3; select * from MyTable;
Which is fine. It would be nicer if it didn't need semicolons, but okay, i'll live with it. But now, in addition, this apparently isn't enough. Just because i've given DB2 some statements to run, doesn't mean that it will run them. For some reason, i have to tell it that the SQL it just received really is all together in one "batch" (to steal a MSSQL term)
BEGIN ATOMIC DECLARE UserID integer; SET UserID = ( SELECT application_ID() FROM sysibm.sysdummy1 ); update MyTable SET UserID = UserID WHERE UserID IS NULL; delete from MyTable WHERE UserID = 3; select * from MyTable; END
But not only that, i have to actually begin the batch with the keywords BEGIN ATOMIC and end the batch with END. So as i understand it, just sending a bunch of SQL to DB2 is not enough for it to decide to run the batch, i have to explicitly tell it that it is a batch. Fine, okay, messy, but i think i understand.
But wait, i don't understand. Because i can send the SQL to create a stored procedure
CREATE PROCEDURE doStuff(...) BEGIN ... END
and i don't have to wrap the batch in BEGIN ATOMIC..END e.g.
BEGIN ATOMIC CREATE PROCEDURE doStuff(...) BEGIN ... END END
So perhaps because it is a CREATE PROCEDURE, or CREATE TRIGGER, or CREATE TABLE, etc that i can omit the BEGIN ATMIC...END around the statement in those batches. Perhaps it is because a CREATE PROCEDURE, CREATE TRIGGER, CREATE TABLE itself is a single statement that it doesn't need to be wrapped. Maybe batches that only consist of a single statement don't need to be wrapped. No, that's not true either:
DECLARE myValue int;
fails also. Maybe Create XXXXX statements are just special like that.
But now, to throw another level of confusion into it, inside a CREATE TRIGGER, you DO have to have BEGIN ATOMIC...END, but not inside a CREATE PROCEDURE.
So, if you read this, please try not to respond to things in detail. Hopefully you can see my confusion, and this must be because i have a different mental picture of how SQL Server is given and runs T-SQL and how DB2 is given and runs T-SQL. If you can see the error in my understanding, and point out exactly where my thinking is wrong - that would be great. It would be nice to have an understanding, rather than hoping understanding will come after being exposed to dozens of disprate examples.
Serge Rielau - 08 Mar 2006 01:26 GMT OK.. 9 days of labour.. some children appear to cause more trouble than others ;-)
Procedural statements are not supported as independent statements by DB2.
That is you can do: CREATE..., DROP.., GRANT, REVOKE, ALTER DECLARE cursors, FETCH, CLOSE (and implied SELECT, VALUES cursors from CLP) UPDATE,DELETE, INSERT, MERGE CALL BEGIN ATOMIC .. END
That's it!
DECLARE variable, SET statement, etc are not 'real' SQL statement. They must be NESTED in a procedure, trigger, function or said BEGIN ATOMIC
So if you want to run a script with logic from the client you have to use BEGIN ATOMIC .. END.
Now talking of semicolons. The DB2 engine knows semicolon only inside of procedures. However semicolon is often also used by query tools as 'go'. So what happens is that the query tools is chopping up the procedure (or trigger ...) and sends pieces of the statement, which of course cause -104 syntax error (unexpected end of statement)
Now I'm somewhat unclear on what query tool you are using. E.g. the IBM provided tools such as the JDBC Type 4 driver (AFAIK) detect the BEGIN ATOMIC, an CREATE PROCEDURE keywords and suppress the batching. Could it be you are using some MS driver which is ignorant to DB2?
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 08 Mar 2006 14:58 GMT > Procedural statements are not supported as independent statements by DB2. > [quoted text clipped - 5 lines] > CALL > BEGIN ATOMIC .. END On some level i wondered if that was how DB2 did it. But i convinced myself that such a scheme is just too complicated to be true, and i assumed that i had some fundamental misunderstanding about what is going on.
Is there a complete list somwhere of what i can and cannot run? Specifically, i'm concerned about the "implied" SELECT and VALUES. My confusion comes from the fact that sometimes i can just run SELECT * FROM ..., and other times i have to declare a cursor for a select, and then leave the cursor open. i don't see OPEN in your list.
In fact, a quick check of the IBM DB2 Universal Database SQL Reference Volume 1 and 2 makes no mention of the keyword BEGIN except for "BEGIN DECLARE SECTION". Neither does the "DB2 Information Center" website. Can you point me to some references on this?
Brian Tkatch - 08 Mar 2006 15:28 GMT >But i convinced myself that such a scheme is just too complicated to be true, and i assumed that i >had some fundamental misunderstanding about what is going on. Welcome to the non-MS/Windows world. Where you are expected to understand what your are doing. :)
>My confusion comes from the fact that sometimes i can just run SELECT * FROM >..., and other times i have to declare a cursor for a select A SELECT statement can be run outside a block of code, a DECLARE within.
The difference is, SELECT is a "statement" and DECLARE is a "control statement". Both clearly delineated in SQL Reference Volume 2.
Generally, the beginning of the documentate for a particular statement says when it can (and sometimes when it cannot) be executed.
B.
Ian Boyd - 08 Mar 2006 16:41 GMT > Welcome to the non-MS/Windows world. Where you are expected to > understand what your are doing. :) They have databases on computers these days. i know what i'm doing, and computers are powerful enough these days to know as well; or at least proceed with the only possible course of action.
>>My confusion comes from the fact that sometimes i can just run SELECT * >>FROM [quoted text clipped - 8 lines] > Generally, the beginning of the documentate for a particular statement > says when it can (and sometimes when it cannot) be executed. That explains why the reference doesn't include some statements, their not the right "kind" of statements. i see the majority of the reference is in a section called "Statements". i don't see a corresponding section of "control statements", nor is the keyword DECLARE in the index. Is there a Reference Volume 3 that documents the "control statements?" Are there are more kinds of statements?
[Comicbook Guy] Umm, excuse me. Clearly select is a statement, and declare is a control statement. Thank you.
Brian Tkatch - 08 Mar 2006 19:16 GMT >They have databases on computers these days. i know what i'm doing, and >computers are powerful enough these days to know as well; or at least >proceed with the only possible course of action. The day DBs do things for me, is the day i stop doing databases. I actually despise Windows mostly because of these assumptions. I love DBs, because they are so simple, and make no assumptions.
>That explains why the reference doesn't include some statements, their not >the right "kind" of statements. Close. It's because, they are not statements.
>i see the majority of the reference is in a section called "Statements". i >don't see a corresponding section of "control statements" In my (offline) copy, Chapter 1 is "Statements" and Chapter 2 is "SQL control statements".
>, nor is the keyword DECLARE in the index. It is absolutely in the index. Though, it is not a bookmark.
It is in Chapter 2.=>Compound Statement (Procedure) under "SQL-variable-declaration".
A search of the index (which is a bookmark) found it for me pretty easily.
B.
Dave Hughes - 08 Mar 2006 19:30 GMT [snip]
> The day DBs do things for me, is the day i stop doing databases. You hand-crank the execution plan for all your queries? Wow ... hardcore man! (joking :-)
> I actually despise Windows mostly because of these assumptions. I love > DBs, because they are so simple, and make no assumptions. I'd take issue with this in one particular area. I've always liked that one can tweak just about *any* performance parameter in DB2. That said, I've come to enjoy the ability added in more recent versions to have the tools figure out an "optimum" configuration, or in the most recent versions to just set the parameter to AUTOMATIC and have the database look after itself.
I'd be extremely disappointed if such configuration parameters were ever removed completely from manual control ... but I do appreciate a bit of "intelligence" being added to the system, provided it's optional
:-) Cheers,
Dave.
Brian Tkatch - 09 Mar 2006 02:40 GMT Point taken. :)
Obviously the software should do some things, just don;t take my power to change them away.
What you said.
B.
Ian Boyd - 08 Mar 2006 20:25 GMT > The day DBs do things for me, is the day i stop doing databases. I > actually despise Windows mostly because of these assumptions. I love > DBs, because they are so simple, and make no assumptions. The running joke at the office is the DB2 "WARNING: Everything is okay!" dialog box.
i hit "OK" to save my changes to, for example, a table. Everything saves okay, but DB2 feels compelled to pop up a big dialog with a lot of text in it. Obviously something bad happened, because if everything saved okay after i told you to save, the edit table screen would go way, and we'd be done.
So each and every time we see one of these boxes pop up, we have to read it:
DB2 Message Commands attempted <some sql that i didn't ever enter> The command completed successfully.
Explanation: No errors were encountered during the execution of this command. User Response: No action required.
Warning! Everything is okay.
It is just as stupid as installing the game Ghost Recon a few years ago, a dialog box pops up, "You have enough free space on this drive to install the game. Proceed?" As if i needed to know that.
<StartOfRanging @skip="yes"> Or another one, i want to shrink a varchar field length:
DBAINTRN The table and its related objects will be dropped and re-created.
Changing the definition of a column attribute involves a LOAD operation. If the database is recoverable, a load copy will be taken for the table being altered. The load copy will be saved as SUPERDUDE.AUDIT_LOG_table.dat. You can delete the load copy file once a backup has been taken for all the related tablespaces.
Would you like to proceed?
Would i like to proceed? Well, i don't know. i didn't ask you to drop and re-create the table and all it's dependant objects. i told you to shink a column from 128 to 100 characters. You do whatever it is you have to do to do it. Are you trying to ask me if i'm okay with the various steps you have to do to perform that operation? Why wouldn't i be? My only choices are to either save my changes or not. i said save, so do it.
Some people will argue, "But the table will have to be dropped and renamed and all keys will recreated. It could potentially be a long operation and maybe the user didn't realize it would take so long to do - so we need to get their permission before doing it. Or worse yet, what if there's a power failure, and something is left in a broken state. At least the user knows that DB2 was performing this relativly big operation. We have to inform the user before we just go ahead and do this."
No you don't. i said save, you save. You do whatever it is you do when you have to save. If it takes a long time, i'm okay with that, because i was changing table structure - i'll expect it to take a long time.
And with the nulls. Why can't it implicitly cast a NULL to the type of the column? What alternative is there? You are perfectly okay casting other types around, why not NULL? Null is the lack of data, it is nothing, it is not being. People will argue,
"But DB2 is a strongly typed system, and null doesn't have the same type as integer. What if the user didn't mean to put a NULL into that column, and we went ahead and did it anyway, that would be bad. If the user really meant to put null in this field they should indicate that by casting it to the proper target data type."
No i don't. i said put null in this column. Your choices are to put it in the column, or not. So why would you not do it? Implicitly cast it and get it done. Just do it. i should have to tell twice, when everything knows that's what i want done. Even the village idiot comes to that conclusion. </StartOfRanging>
>>That explains why the reference doesn't include some statements, their not >>the right "kind" of statements. > > Close. It's because, they are not statements. i guess this is where some help with examples would be extraordinarily useful.
>>i see the majority of the reference is in a section called "Statements". i >>don't see a corresponding section of "control statements" > > In my (offline) copy, Chapter 1 is "Statements" and Chapter 2 is "SQL > control statements". SQL Reference Volume 1 Contents About this book Chapter 1. Concepts Chapter 2. Language elements Chapter 3. Functions Chapter 4. Queries Appendix A. SQL limits ... Appendix Q. Notices Index Contacting IBM
SQL Reference Volume 2 Contents About this book Statements Appendix A. DB2 Universal Databse technical information Appendix B. Notices Index Contacting IBM
These are two PDF files that are referred to by the online documentation. i reach the online documentation from Control Center by hitting: Help->About
On the web-site, i see Reference SQL How to read the syntax diagrams Common syntax elements Language elements Functions Procedures Queries Statements Reserved schema names and reserved words SQL statements allowed in routines Communications areas, descriptor areas, and exception tables Explain tables Explain register values Japanese and traditional-Chinese extended UNIX code (EUC) considerations Backus-Naur form (BNF) specifications for DATALINKs
>>, nor is the keyword DECLARE in the index. > > It is absolutely in the index. Though, it is not a bookmark. > > It is in Chapter 2.=>Compound Statement (Procedure) under > "SQL-variable-declaration".
> A search of the index (which is a bookmark) found it for me pretty > easily. i gotta find this book, web-site, pdf, help file, or eBook you got.
Jeroen van den Broek - 09 Mar 2006 00:00 GMT [..]
>>>That explains why the reference doesn't include some statements, their >>>not [quoted text clipped - 68 lines] > > i gotta find this book, web-site, pdf, help file, or eBook you got. Maybe Brian was referring to (an older version of) the SQL Reference for DB2 on zOS ("Mainframe"). The current (v8) version for that book contains the following TOC:
SQL Reference Contents About this book Summary of changes to this book Chapter 1. DB2 concepts Chapter 2. Language elements Chapter 3. Functions Chapter 4. Queries Chapter 5. Statements Chapter 6. SQL control statements Appendix A. Limits in DB2 UDB for z/OS Appendix B. Reserved schema names and reserved words Appendix C. Characteristics of SQL statements in DB2 UDB for z/OS Actions allowed on SQL statements SQL statements allowed in external functions and stored procedures SQL statements allowed in SQL procedures Appendix D .... Appendix H. Sample user-defined functions Notices Glossary Bibliography Index Readers' Comments -- We'd Like to Hear from You
This book, as all other ones for DB2 v8 for z/OS can be found here: http://www-306.ibm.com/software/data/db2/zos/v8books.html
If you want similar documentation for DB2 on Linux, Unix and Windows you have to go here: http://www-306.ibm.com/software/data/db2/udb/support/manualsv8.html where you will find the SQL Reference (Vol 1 and 2) you already have. Next to those however, you may want to take a look at the Command Reference. The Master Index may also be usefull for determining which document you need for a specific purpose.
HTH.
 Signature Jeroen
Jeroen van den Broek - 09 Mar 2006 00:16 GMT [..]
> If you want similar documentation for DB2 on Linux, Unix and Windows you > have to go here: [quoted text clipped - 4 lines] > The Master Index may also be usefull for determining which document you > need for a specific purpose. More specific w.r.t. the Command Reference:
Chapter 4. Using command line SQL statements
 Signature Jeroen
Brian Tkatch - 09 Mar 2006 02:36 GMT >was referring to (an older version of) the SQL Reference for DB2 on zOS ("Mainframe"). Version 8 for LUW.
Or at least that's what they have on the corparate intranet.
B.
Ian Boyd - 09 Mar 2006 14:28 GMT > If you want similar documentation for Windows you have to go here: > http://www-306.ibm.com/software/data/db2/udb/support/manualsv8.html
> where you will find the SQL Reference (Vol 1 and 2) you already have. Yes.
> Next to those however, you may want to take a look at the Command > Reference. No.
> The Master Index may also be usefull for determining which document you > need for a specific purpose. i see my problem now. This "Master Index" contains an index into all other documents. If you click on an index entry, i will load that PDF and jump to the page. In my case, it contains index entries that the target PDF itself doesn't include. My mistake was trying to use the index in "SQL Reference Volume 2 Version 8.2". That was my mistake, that was folly.
i was looking for "DECLARE", when instead i should be looking for "Compound SQL (Procedure)". Then you scan that chapters' SQL Diagrams for one that contains the word DECLARE, which in my case is "SQL-Variable-declaration."
Then scroll down a few pages, looking for "SQL-Variable-declaration". Then, ping-pong between the explanation and the SQL diagram in order to try to infer what the syntax is. Then scroll randomly a few pages forward and a few pages back hoping for an example - and in this case there is one.
Intuitive.
i am SO ready for IBM.
Brian Tkatch - 09 Mar 2006 16:31 GMT > Then, ping-pong between the explanation and the SQL diagram in order to try to infer what the syntax is. Not infer. the diagram is clear, according to the guidelines presented in "About this book" subsection "How to read the syntax diagrams".
You may not like the IBM diagrams, but they are indeed very clear.
B.
Ian Boyd - 09 Mar 2006 18:46 GMT > You may not like the IBM diagrams, but they are indeed very clear. The same diagrams are in the ANSI spec. They are very clear once you already know the syntax.
Brian Tkatch - 09 Mar 2006 02:39 GMT I guess you never saw MS Word's message "you must click OK to exit" with one button marked "OK".
DB2 is an IBM product, and has a message and an error code for *everything*. It's part and parcel of IBM to document everything. (Worked beautifully in OS/2.)
As for NULLs, i have the same gripe.
As for "make it works anyway, cus i cliked "save". I hope you are never my DBA. :P
B.
Serge Rielau - 08 Mar 2006 16:03 GMT >> Procedural statements are not supported as independent statements by DB2. >> [quoted text clipped - 15 lines] > ..., and other times i have to declare a cursor for a select, and then leave > the cursor open. i don't see OPEN in your list. I forgot OPEN :-) The interactive tools (like command center and CLP) have short hands for queries. That is when you type VALUES or SELECT interactively they will declare a cursor for you, open it, fetch all the rows and close. Then they pretty print the output.
> In fact, a quick check of the IBM DB2 Universal Database SQL Reference > Volume 1 and 2 makes no mention of the keyword BEGIN except for "BEGIN > DECLARE SECTION". Neither does the "DB2 Information Center" website. Can you > point me to some references on this? This is the root for SQL Procedure logic: http://publib.boulder.ibm.com/infocenter/db2luw/v8//topic/com.ibm.db2.udb.doc/ad min/r0004239.htm This is the root for the simpler command line scripting: http://publib.boulder.ibm.com/infocenter/db2luw/v8//topic/com.ibm.db2.udb.doc/ad min/r0004240.htm
Here are the sentences for the GOTO statement (random example): "GOTO statement
The GOTO statement is used to branch to a user-defined label within an SQL procedure.
Invocation
This statement can only be embedded in an SQL procedure. It is not an executable statement and cannot be dynamically prepared."
You implicitly raise an interesting point though. The SQL Reference is "dictionary" it is as little the right tool to learn the basics of SQL as any dictionary.
You are used to MS SQL Server "Books Online" which is more of a guide. It describes what matters example driven). The DB2 SQL Ref is the _exact_ specification of DB2's SQL.
There are plans to deliver a SQL Guide in a future release which will be more appropriate and have information such as which statement can be used where, and include scenario based examples.
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 08 Mar 2006 16:57 GMT > This is the root for SQL Procedure logic: > http://publib.boulder.ibm.com/infocenter/db2luw/v8//topic/com.ibm.db2.udb.doc/ad min/r0004239.htm > This is the root for the simpler command line scripting: > http://publib.boulder.ibm.com/infocenter/db2luw/v8//topic/com.ibm.db2.udb.doc/ad min/r0004240.htm i get it. Some statements are only valid inside other statements. If of course be convient if they would just work.
> This statement can only be embedded in an SQL procedure. It is not an > executable statement and cannot be dynamically prepared." Why? It can't be a technical limitation, and there is little value in making things more difficult for people to use. Is it the standard? And if so how many companies in the consortium are trying to change it? It's fair to say that in the end this stuff is meant to be used by developers, not just computer scientists.
> You implicitly raise an interesting point though. > The SQL Reference is "dictionary" it is as little the right tool to learn > the basics of SQL as any dictionary. Every other computer language has keywords or tokens, and someplace you can open a reference manual and get an explanation for that token, or a reference to where it is used.
> You are used to MS SQL Server "Books Online" which is more of a guide. > It describes what matters example driven). > The DB2 SQL Ref is the _exact_ specification of DB2's SQL. Which is about a dry a read as ISO/IEC 9075 is, albeit more helpful.
> There are plans to deliver a SQL Guide in a future release which will be > more appropriate and have information such as which statement can be used > where, and include scenario based examples. An index would be nice. Seaching a web-site, pdf, google groups, or the internet for "ibm db2 set" doesn't help so much. But if i could type SET and be presented with the index entries that someone has already taken the time to pre-select, would be so so SO SO SO much more useful.
In the Books Online, i rarely use the "contents" and i rarely use "search". i use the index almost exclusivly. If i want help on, for example, SET, i type the word SET and am presented with the documentation on the SET keyword. Doing a word search for "SET" would be folly.
Knut Stolze - 08 Mar 2006 07:25 GMT > i've never used any idea similar to > (SELECT 5 UNION SELECT 6) AS X > > i've never had a problem where i needed to join to such virtual table. I would not call this a "virtual" table. It is a table (like views are tables). The major issue here is where the data of the table comes from. In this case, the table is constructed on the fly.
> Like i said before, i'll have to figure out where VALUES would be useful > to me. [quoted text clipped - 9 lines] > > So the column gets renamed from "" to "ProcessID." Note that DB2 names expressions that are returned from a query itself (it numbers them) if they don't have an explicit name. That's why you see the "1" or "2" in the following output:
$ db2 "select 1+2+3, 4+5+6 from sysibm.sysdummy1"
1 2 ----------- ----------- 6 15
1 record(s) selected.
Same thing here:
$ db2 "values ( 1+2+3, 4+5+6 )"
1 2 ----------- ----------- 6 15
1 record(s) selected.
And those "1" or "2" can be used in a Java application when you fetch the data from the result set by column name.
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Ian Boyd - 08 Mar 2006 14:10 GMT > $ db2 "select 1+2+3, 4+5+6 from sysibm.sysdummy1" > [quoted text clipped - 16 lines] > And those "1" or "2" can be used in a Java application when you fetch the > data from the result set by column name. Unless someone changed the query to SELECT 3.14159, 1+2+3, 4+5+6
1 2 3 -------- -------- -------- 3.14159 6 15
1 record(s) selected.
And now all the application logic has to be rewritten.
Serge Rielau - 08 Mar 2006 15:01 GMT >> $ db2 "select 1+2+3, 4+5+6 from sysibm.sysdummy1" >> [quoted text clipped - 27 lines] > > And now all the application logic has to be rewritten. You two got yor wires crossed.. Knut is talking about correlation names (above the ----- line). You are now talking about result types.
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 08 Mar 2006 17:00 GMT >select 1+2+3, 4+5+6 from sysibm.sysdummy1 1 2 ----------- ----------- 6 15
> SELECT 3.14159, 1+2+3, 4+5+6 1 2 3 -------- -------- -------- 3.14159 6 15
> You two got yor wires crossed.. Knut is talking about correlation names > (above the ----- line). > You are now talking about result types. ?
i thought we were talking about correlation names and how they are still necessary even if there is only one column in the results set.
Knut Stolze - 09 Mar 2006 08:50 GMT > Unless someone changed the query to > SELECT 3.14159, 1+2+3, 4+5+6 I guess you mean VALUES 3.14159, 1+2+3, 4+5+6
> 1 2 3 > -------- -------- -------- [quoted text clipped - 3 lines] > > And now all the application logic has to be rewritten. True. But my answers would be (a) Why is the additional column not appended? Then you don't break anything. (b) I don't think this is a big deal in reality. For several decades now the the fetching of values from a result set is based on the order of the columns. So far there hasn't been a great outrage on this. Granted, the fetching using column names is a nice feature. (c) You could always wrap the VALUES into a SELECT to give the column names
SELECT * FROM TABLE ( VALUES ( 3.14159, 1+2+3, 4+5+6 ) ) AS t(a, b, c)
or use sysibm.sysdummy1 (or DUAL in Oracle).
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Ian Boyd - 09 Mar 2006 14:44 GMT >> Unless someone changed the query to >> SELECT 3.14159, 1+2+3, 4+5+6 > > I guess you mean VALUES 3.14159, 1+2+3, 4+5+6 Yes, i slipped, i was focused on the concept. i should have written:
SELECT 3.14159, 1+2+3, 4+5+6 FROM sysibm.sysdummy1
> True. But my answers would be > (a) Why is the additional column not appended? Then you don't break > anything. Cause i didn't.
> (b) I don't think this is a big deal in reality. Granted, the > fetching using column names is a nice feature. From almost day one, i got burned fetching column values by ordinal. It's just a bad idea. Yes i could do it, and i could be forced to keep the ordinal location of every field in every table, result set, or query. But it makes it easier for separate systems to talk to each other if each side talks to the other through named columns. It makes systems much more resiliant to changes. It's just good practice.
> For several decades now > the the fetching of values from a result set is based on the order of the > columns. They have databases on computers now. It's not a huge performance penalty to lookup columns by name. It just isn't. No new systems (i.e. those not written in the last few decades) lookup fields by ordinal. No web-sites do it, no desktop applications do it.
>So far there hasn't been a great outrage on this. The outrage comes when someone tries to maintain legacy systems, for example removing legacy columns that are no longer used for the business. You delete the column, and every application that depends on column's by ordinal location break. So now we're stuck with junk because someone never bothered to make their system flexible and smart.
Brian Tkatch - 09 Mar 2006 16:37 GMT >From almost day one, i got burned fetching column values by ordinal. It's >just a bad idea. Yes i could do it, and i could be forced to keep the >ordinal location of every field in every table, result set, or query. Not in the TABLE, in the query. And the query changes per application, so no problem. If the query is in a stored PROCEDURE, and outputs a result set, it is best to use the VALUES inside a SELECT statement as Knut pointed out.
B.
Ian Boyd - 09 Mar 2006 18:48 GMT > And the query changes per application, > so no problem. Not when a query is the query was written in one application and used by another.
> If the query is in a stored PROCEDURE, and outputs a > result set, it is best to use the VALUES inside a SELECT statement as > Knut pointed out. How do you give names to the fields returned from a SELECT of a VALUES table?
Dave Hughes - 09 Mar 2006 19:56 GMT > > And the query changes per application, > > so no problem. [quoted text clipped - 8 lines] > How do you give names to the fields returned from a SELECT of a > VALUES table? I'm pretty sure I've provided the syntax for this in a couple of other comments, but maybe I didn't indicate it explicitly:
SELECT COLA, COLB, COLC FROM ( VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9) ) AS TEMP(COLA, COLB, COLC)
The "AS" bit is mandatory and provides a name for the table produced by VALUES. The field aliases in brackets after AS TEMP are optional, but allow you to assign names to the columns in the VALUES table, which can then be referenced in the enclosing SELECT statement as above. Though I could just as easily have done:
SELECT * FROM ( VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9) ) AS TEMP(COLA, COLB, COLC)
HTH,
Dave.
Ian Boyd - 09 Mar 2006 20:17 GMT > I'm pretty sure I've provided the syntax for this in a couple of other > comments, but maybe I didn't indicate it explicitly: [quoted text clipped - 9 lines] > then be referenced in the enclosing SELECT statement as above. Though I > could just as easily have done: Thank you for that. i do remember seeing the post, but i thought that the COLA, COLB, COLC were placeholders for something...i dunno. i didn't appreciate that it is the way to give names to the columns created by VALUES.
VALUES is a cool construct. i don't know if it's in SQL92/99/etc, but SQL Server should have something like it - even if i can't think of good uses for it right now :)
Serge Rielau - 10 Mar 2006 16:19 GMT > VALUES is a cool construct. i don't know if it's in SQL92/99/etc, but > SQL Server should have something like it - even if i can't think of good > uses for it right now :) Using VALUES you can PIVOT tables and you can also simplify that UPDATE trigger of yours into a single INSERT statement.
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Ian Boyd - 10 Mar 2006 16:23 GMT >> VALUES is a cool construct. i don't know if it's in SQL92/99/etc, but >> SQL Server should have something like it - even if i can't think of good >> uses for it right now :) > Using VALUES you can PIVOT tables and you can also simplify that > UPDATE trigger of yours into a single INSERT statement. Whoa, whoa, slow down.
Let me figure out how to do SELECTs first :)
Will Honea - 10 Mar 2006 05:40 GMT > I'm pretty sure I've provided the syntax for this in a couple of other > comments, but maybe I didn't indicate it explicitly: [quoted text clipped - 3 lines] > VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9) > ) AS TEMP(COLA, COLB, COLC) What is the semantic difference between your syntax and the form
WITH TEMP(COLA,COLB,COLC) AS ( SELECT .... )
They appear equivilant - am I missing something?
 Signature Will Honea
Dave Hughes - 10 Mar 2006 13:00 GMT > > I'm pretty sure I've provided the syntax for this in a couple of > > other comments, but maybe I didn't indicate it explicitly: [quoted text clipped - 10 lines] > > They appear equivilant - am I missing something? The WITH ... construct is a "common table expression" which was syntax introduced in the SQL-99 standard. Functionally, both your version and my version above are identical.
That said, common table expressions are considerably more powerful than sub-selects and (in my personal opinion) a lot clearer especially if a query includes many sub-selects. One of the things you can do with common table expressions (that you can't do with ordinary sub-selects) is "recursive" queries. I haven't seen them used much in practice, and you've got to be a bit careful with (it's possible to make an infinitely recursive query), but there's some interesting examples in the DB2 Info Center under Reference / SQL / Queries / Select-statement (see the "Recursion example: bill of materials" section).
One last thing, using a common table expression instead of a sub-select in my example, one wouldn't even need a SELECT expression around the VALUES expression:
WITH TEMP(COLA, COLB, COLC) AS ( VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9) ) SELECT ...
Anyway, thanks for bringing that up - I should have mentioned common table expressions in my reply, but forgot :)
Dave.
Knut Stolze - 13 Mar 2006 10:39 GMT >> > I'm pretty sure I've provided the syntax for this in a couple of >> > other comments, but maybe I didn't indicate it explicitly: [quoted text clipped - 14 lines] > introduced in the SQL-99 standard. Functionally, both your version and > my version above are identical. Not quite the same - there are some very small differences that you usually don't have to worry about. The common table expression is guaranteed to be evaluated before the SELECT statement. Also, the CTE is evaluated exactly once. The DB2 optimizer is not given a choice to copy the CTE in several branches of the statement if it thinks that would be better. This is usually only relevant for non-deterministic/external action stuff.
Besides that, CTEs are identical to the sub-select.
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Serge Rielau - 13 Mar 2006 13:16 GMT >>>> I'm pretty sure I've provided the syntax for this in a couple of >>>> other comments, but maybe I didn't indicate it explicitly: [quoted text clipped - 21 lines] > > Besides that, CTEs are identical to the sub-select. What you describe there are not the CTEs I know. The rules fro non determinism are teh same for derived tables, views and CTE. Order of execution is only honored for CTE if there is a reason to honor them (like SELECT FORM INSERT/UPDATE/DELETE).
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Knut Stolze - 13 Mar 2006 13:19 GMT > What you describe there are not the CTEs I know. The rules fro non > determinism are teh same for derived tables, views and CTE. > Order of execution is only honored for CTE if there is a reason to honor > them (like SELECT FORM INSERT/UPDATE/DELETE). Oh, all right. The SQL standard does make this distinction and I assumed it applies to DB2 as well.
 Signature Knut Stolze DB2 Information Integration Development IBM Germany
Serge Rielau - 10 Mar 2006 16:15 GMT > How do you give names to the fields returned from a SELECT of a VALUES > table? SELECT * FROM (VALUES (1, 2, 3)) AS T(c1, c2, c3)
Cheers Serge
 Signature Serge Rielau DB2 Solutions Development IBM Toronto Lab
Dave Hughes - 08 Mar 2006 18:48 GMT |
|