On 13/11/2010, at 10:33 AM, Olaf Schmidt wrote:

>>>> From: "Olaf Schmidt"
>>>> Wednesday, November 10, 2010 9:07:19 AM
>>>> 
>>> There was a somewhat similar sounding post (from BareFeetWare,
>>> sent on 20.Oct to this list) who also encouraged, to include
>>> "more logic" into the SQLite-Files itself, to reach more "portability".
>> 
>> That post of mine is archived here:
>> 
> http://sqlite.org:8080/cgi-bin/mailman/private/sqlite-users/2010-October/025096.html
> 
> Yep, that was it.
> 
>> For the record, I (for BareFeetWare) was advocating implementing database 
>> logic in constraints and triggers, rather than in application code. I was 
>> not actually talking about stored procedures.

> After reading your posting again, it seems I had a "wrong image" in the back 
> of my mind, regarding your post, sorry.
> 
> Since you are talking about *database-logic* - our opinions do not differ 
> that much I'd say...

> ...use "DB-internal mechanisms" only in a range, which is common among 
> different DB-engines (Triggers for example, to ensure referential integrity 
> at least)."
> 
> And constraints, which I left out, belong into the same category, since they 
> are "common enough" too (among different DB-engines).

> Nothing wrong with Triggers and Constraints (the "database logic", as you 
> call it). Things which ensure (force) consistency on your Data belong into 
> the DB. They are usually well portable between different Engines (good 
> DB-Import-Tools can recognize and understand most of these - where importing 
> vendor-specific Stored-Procedures into another Backend can be adventurous at 
> least, if we talk about larger or complex procedures).

OK, we'll agree to... agree ;-) Database internal logic (integrity checks etc) 
are best handled in the database code (SQL), such as in constraints and 
triggers. I didn't know what you meant by "range".

> "business-logic" or "business layer", then that's something, what in my 
> opinion belongs into a shareable Component (usually a Dll), written
> in a normal language - but I think I already made my points, let's not repeat 
> them again - and it's after all only a personal opinion.

I guess we both agree that for business logic (as opposed to database logic, 
discussed above), a procedure of some kind is obviously required. In this 
situation, I advocate that as much as possible is done in SQL, by using "where" 
clauses and manipulating sets rather than using "if/then" branching structures 
and iterating through loops, respectively. This is more efficient and exploits 
SQL data storage optimisations. In fact I think that the availability of 
if/then and repeat loops in a database often entices people into bad habits of 
procedural programming where set programming should be used instead.

Do you have procedures that require branching structures? Can it not be better 
achieved by set logic?

If there's no other way than to have branching structures, then I think I see 
what you're saying: that it's better to take care of the branching structures 
in an external code layer than in an SQL procedural language (which SQLite 
doesn't have, currently). I think you're saying that SQL procedure branching 
structures aren't standard enough across SQL flavours to make it portable. In 
short, if you're more likely to change the choice of SQL flavor (eg SQLite to 
MySQL) than application code (eg perl vs python vs PHP vs Objective-C) then 
you're better off putting the branching structures in the application code. 
Correct? This choice would boil down to the likelihood of changing each (ie SQL 
flavor vs application code environment).

>> Why would we want to perform stored procedures?
> 
> Ehhmm, because a "bunch of well-organized and consistent data-records" is not 
> (yet) an Application? ;-)

LOL, yes, true. The application code has to drive the GUI or html input/output 
or whatever, but when the application code gets to the point of getting or 
setting data in the database, then it should ideally be done each time as one 
SQL call, rather than having a pile of application branches that makes several 
SQL calls.

>> If you have code (in either environment) that is looping or grabbing one 
>> result and sticking it in a second query, then your approach is probably 
>> flawed.

> As you say: "probably" ... because "it depends" ... (maybe your application 
> wants to show "details" in a delayed fashion - e.g. when a Node in a Treeview 
> gets "expanded").

Good example. At the point where the user requests expanded details (eg by 
clicking on a button), that obviously kicks off application code. As far as its 
interaction with the database, simplistically, it would have to do something 
like get the key values in the current row, check whether it exists in the 
details set, get the detail data. What I'm saying is that this should be done 
as one SQL call, which most likely doesn't require any branching logic within 
that call.

So it should look something like this, with just one SQL call:

array filteredDetailResults  = execQuery(
        select "Product Code", "Product Name", Quantity, Price
        from "Invoice Items"
                join "Invoice List" on "Invoice Items"."Invoice Number" = 
"Invoice List"."Invoice Number"
                left join "Item List" on "Invoice Items"."Product Code" = "Item 
List"."Product Code"
        where "GUI Selection Flag" = 1
)
show filteredDetailResults

And not look like this (psuedo application code), with application code 
reinjecting the results of separate SQL calls into each other:

int invoiceNumber = execQuery(
        select "Invoice Number" from "Invoice List" where "GUI Selection Flag" 
= 1;
)
array detailResults = execQuery(
        select "Product Code", "Product Name", Quantity, Price from "Invoice 
Items" where "Invoice Number" = ?;
        arguments: invoiceNumber
)
for (detailResult in detailResults)
{
        string productCode = value of column "Product Code" in detailResult
        bool isAProduct = execQuery(
                select "Is a Product" from "Item List" where "Product Code" = ?;
                arguments: productCode
        )
        if (isAProduct)
                append detailResult to filteredDetailResults
}
show filteredDetailResults

> Anyways, hope my position is more clear to you now

Yes, thank you O:-)

> and - (since you made this request) - you feel "enlightened enough" in the 
> meantime <g>.

Yes, indeed, please enlighten me further, with some sample code of any 
procedural code that you think is necessary to intermix application code with 
multiple SQL calls, or any branching logic based on data returned that affects 
a subsequennt database call.

Thanks,
Tom
BareFeetWare

 --
Comparison of SQLite GUI tools:
http://www.barefeetware.com/sqlite/compare/?ml

_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to