[fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-24 Thread Reinier Olislagers
On 22-10-2011 15:33, michael.vancanneyt-0is9kj9s...@public.gmane.org wrote:
 
 
 On Sat, 22 Oct 2011, Marco van de Voort wrote:
 
 In our previous episode, Felipe Monteiro de Carvalho said:
 Ok, now I want to insert a record in my table and I would like to
 obtain the auto-generated PrimaryKey

 This is a classic problem, since SQL simply doesn't support this.

 So all DBs do something else, for postgresql there are sequence
 objects that
 can be queried, while other allow to return the id of the autogenerated
 fields.

 Afaik sqldb does not abstract this yet.
 
 That's because it can't be abstracted correctly. There are 2
 incompatible mechanisms.
 
 1. autogenerated fields (mysql, MS SQL server) which must be retrieved
 after the insert using a special API.
 
 2. or sequences, which must be generated manually before the insert
 (DB2, Oracle, Firebird) using a special
API, but which may or may not be generated in an AFTER INSERT trigger.
In which case it's impossible to retrieve the sequence value after
 the insert except by re-reading the record.

Correct, but for option 2. - at least in Firebird - BEFORE INSERT
triggers are often used, not AFTER INSERT.
See eg http://www.firebirdfaq.org/faq29/

Also, using INSERT...RETURNING it's very well possible to get the
sequence value directly when inserting the data.

What's more incompatible to me is the difference between:
a. manually having to specify a PK, either totally manually or using a
sequence
b. having the DB do it for you, either via an autonumber (your option 1)
or a trigger with a sequence.

The problem is that I think it's very difficult to SQLDB to figure out
whether it's in situation a or b. If in a and the DB supports sequences,
SQLDB will still need to be told which sequence to use.

If in b, we face all the various ways of getting an autonumber or
auto-generated PKs back, see e.g.
https://secure.wikimedia.org/wikipedia/en/wiki/Insert_%28SQL%29#Retrieving_the_key

When in b, we then get the issue of getting the primary key:

Doing it in one statement:
INSERT RETURNING for Firebird, Postgresql, Oracle, ?
...

In two:
SCOPY_IDENTITY() for SQL Server 2000 and earlier, or if you don't/can't
use OUTPUT
LAST_INSERT_ID()
Special select statement for DB2


;)
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-24 Thread michael . vancanneyt



On Mon, 24 Oct 2011, Reinier Olislagers wrote:


On 22-10-2011 15:33, michael.vancanneyt-0is9kj9s...@public.gmane.org wrote:



On Sat, 22 Oct 2011, Marco van de Voort wrote:


In our previous episode, Felipe Monteiro de Carvalho said:

Ok, now I want to insert a record in my table and I would like to
obtain the auto-generated PrimaryKey


This is a classic problem, since SQL simply doesn't support this.

So all DBs do something else, for postgresql there are sequence
objects that
can be queried, while other allow to return the id of the autogenerated
fields.

Afaik sqldb does not abstract this yet.


That's because it can't be abstracted correctly. There are 2
incompatible mechanisms.

1. autogenerated fields (mysql, MS SQL server) which must be retrieved
after the insert using a special API.

2. or sequences, which must be generated manually before the insert
(DB2, Oracle, Firebird) using a special
   API, but which may or may not be generated in an AFTER INSERT trigger.
   In which case it's impossible to retrieve the sequence value after
the insert except by re-reading the record.


Correct, but for option 2. - at least in Firebird - BEFORE INSERT
triggers are often used, not AFTER INSERT.
See eg http://www.firebirdfaq.org/faq29/


Typo on my part, sorry.



Also, using INSERT...RETURNING it's very well possible to get the
sequence value directly when inserting the data.


Yes, but not all DBs support this. We use Firebird a lot, and it didn't
support that construct until version 2.1 or so.

In each case: it's hard to abstract correctly, but nevertheless we'll try
and make managing this easier. Martin's ideas for this are useful.

What's funny is that I never understood how the MySQL/SQL-Server way could
correctly work. For example I have 2 tables, both with an auto-incremental
field. 
Table 1 has an after insert trigger that does an extra insert in table 2. 
When I do an insert in table 1 , what does 'last_insert_id' return ? 
The value for table 2 or table 1 ? 
The last inserted id for your connection is the one for table 2, but you 
need/expect the last id for table 1 :-)


Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-24 Thread Reinier Olislagers
On 24-10-2011 11:14, michael.vancann...@wisa.be wrote:
 On Mon, 24 Oct 2011, Reinier Olislagers wrote:
 Also, using INSERT...RETURNING it's very well possible to get the
 sequence value directly when inserting the data.
 
 Yes, but not all DBs support this. We use Firebird a lot, and it didn't
 support that construct until version 2.1 or so.
Yep, it's one of many really nice cross-db incompatibilities. Long live
SQL ;)
 
 In each case: it's hard to abstract correctly, but nevertheless we'll try
 and make managing this easier. Martin's ideas for this are useful.
Yes, he's got experience with it already - more than you can say of some
armchair theorists like me ;)
 
 What's funny is that I never understood how the MySQL/SQL-Server way could
 correctly work. For example I have 2 tables, both with an auto-incremental
 field. Table 1 has an after insert trigger that does an extra insert in
 table 2. When I do an insert in table 1 , what does 'last_insert_id'
 return ? The value for table 2 or table 1 ? The last inserted id for
 your connection is the one for table 2, but you need/expect the last id
 for table 1 :-)

True. Fortunately, I've never needed to do that ;)

Regards,
Reinier
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-24 Thread Graeme Geldenhuys
On 2011-10-24 14:43, michael.vancann...@wisa.be wrote:
 We will of course support GUID PKs, although in my opinion, there is
 precious little to support as it will in general be client code that
 generates the GUID (unless I am much mistaken in what is common 
 practise) ?

That is indeed the case. There is nothing extra that needs to be added
to SqlDB. Our primary key fields are simply a varchar(36), and we all
know a string value / varchar() is already well supported. ;-)


Regards,
  - Graeme -

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Felipe Monteiro de Carvalho
Hello,

Ok, searching some more I see that select scope_identity() could
return the generated primary key. But how to get the value?

 DBComm.PQConnection.ExecuteDirect(SQLText);

The method above has no return value =(

-- 
Felipe Monteiro de Carvalho
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread michael . vancanneyt



On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote:


Hello,

Ok, searching some more I see that select scope_identity() could
return the generated primary key. But how to get the value?

 DBComm.PQConnection.ExecuteDirect(SQLText);

The method above has no return value =(


Use a TSQLQuery with SQL select scope_identity() as theid and read field 0.

I repeat, do not use ExecuteDirect.

Michael.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Inoussa OUEDRAOGO
 Ok, searching some more I see that select scope_identity() could
 return the generated primary key. But how to get the value?

Better use the RETURNING* clause** as it clearly state the column
value you are expecting; The scope_identity() may be a source of
subtle bugs that are
difficult to resolve, for example :
  what if the table make use of two sequences (yes sometime this is needed)
  what if the table's insert trigger generates a insert query(or
stored procedure) into another table which make use of sequence

(*) http://www.postgresql.org/docs/8.3/interactive/sql-insert.html
(**) this clause is at least supported by Firebird, MS SQL SERVER, ORACLE

-- 
Inoussa O.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Marcos Douglas
On Sat, Oct 22, 2011 at 11:35 AM, Inoussa OUEDRAOGO inouss...@gmail.com wrote:
 Ok, searching some more I see that select scope_identity() could
 return the generated primary key. But how to get the value?

 Better use the RETURNING* clause** as it clearly state the column
 value you are expecting; The scope_identity() may be a source of
 subtle bugs that are
 difficult to resolve, for example :
  what if the table make use of two sequences (yes sometime this is needed)
  what if the table's insert trigger generates a insert query(or
 stored procedure) into another table which make use of sequence

 (*) http://www.postgresql.org/docs/8.3/interactive/sql-insert.html
 (**) this clause is at least supported by Firebird, MS SQL SERVER, ORACLE

Talking about MSSQL Server, the scope_identity() return the ID inside
the scope, ie, return the ID from your INSERT instruction, ignoring
Triggers, for example.
If you use @@IDENTITY then you get the last ID inserted, ie, if you
have triggers you do not know which ID belongs which table.

Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Felipe Monteiro de Carvalho
ugh, any ideas how I can obtain the next sequence value using sqldb
and postgres then?

I have never used sequence values before, and while I am googling I
only found either answers which are specific for a particular
framework (java, djambo, whatever) or people claiming that it should
generate the index automatically! o.O Which clearly it is not doing...
I couldn't yet get a generic answer using SQL supported by Postgres,
or whatever thing which I could reuse in sqldb.

thanks,
-- 
Felipe Monteiro de Carvalho


-- 
Felipe Monteiro de Carvalho
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Marcos Douglas
On Sat, Oct 22, 2011 at 1:33 PM, Felipe Monteiro de Carvalho
felipemonteiro.carva...@gmail.com wrote:
 ugh, any ideas how I can obtain the next sequence value using sqldb
 and postgres then?

 I have never used sequence values before, and while I am googling I
 only found either answers which are specific for a particular
 framework (java, djambo, whatever) or people claiming that it should
 generate the index automatically! o.O Which clearly it is not doing...
 I couldn't yet get a generic answer using SQL supported by Postgres,
 or whatever thing which I could reuse in sqldb.

You can use:
- Stored Procedures (SP): one for each table;
- Dynamic SP: pass the generic SQL to the SP and return the scope_identity();
- GUID: Use a column to save a GUID. The real ID can be autoincrement
but you do not need it. You can found the register using the GUID.

Marcos Douglas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Michael Van Canneyt



On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote:


ugh, any ideas how I can obtain the next sequence value using sqldb
and postgres then?

I have never used sequence values before, and while I am googling I
only found either answers which are specific for a particular
framework (java, djambo, whatever) or people claiming that it should
generate the index automatically! o.O Which clearly it is not doing...
I couldn't yet get a generic answer using SQL supported by Postgres,
or whatever thing which I could reuse in sqldb.


Just a use a TSQLQuery:

With TSQLQuery.Create(Self) do
  try
Database:=MyDatabase;
Transaction:=MyTransaction;
// Replace sequencename with the correct name of the sequence
SQL.Text:='SELECT nextval(''sequencename'')';
Open;
TheNewID:=(Fields[0] as TLargeIntField).AsLargeInt;
close;
  finally
free;
  end;

That's it.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?

2011-10-22 Thread Martin Schreiber
On Saturday 22 October 2011 17.33:11 Felipe Monteiro de Carvalho wrote:
 ugh, any ideas how I can obtain the next sequence value using sqldb
 and postgres then?
 
 I have never used sequence values before, and while I am googling I
 only found either answers which are specific for a particular
 framework (java, djambo, whatever) or people claiming that it should
 generate the index automatically! o.O Which clearly it is not doing...
 I couldn't yet get a generic answer using SQL supported by Postgres,
 or whatever thing which I could reuse in sqldb.
 
 thanks,

Postgres documenatation is here:

http://www.postgresql.org/docs/manuals/
http://www.postgresql.org/docs/8.3/static/functions-sequence.html

MSEgui calls getsqlresult() with the statement

function tmsepqconnection.readsequence(const sequencename: string): string;
begin
 result:= 'select nextval(''' +sequencename+''') as res;';
end;

returns. Instead of the MSEgui getsqlresult() function use a tsqlquery in 
sqldb.

Martin
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal