merry_prince
asked on
Urgent: Delphi5 can't execute sql statement with groupby_clause and parameters.
I try to execute an Oracle sql statement by Delphi5, oracle warns general SQL error. Ora-00979: not a Group By expression. But I execute same sql statement by Toad. Then can get query result.
with Query1, SQL do begin
close;
clear;
Add('select ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD ( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
Add('from TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD ( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
ParamByName('PASSWD').AsSt ring := 'TEST';
ParamByName('SYS_USER').As String := 'SM2-CLM';
Open;
end;
Moreover, I try to imitate a similar SQL statement. It can work normally.
with Query2, SQL do begin
Close;
Clear;
Add('select name, getName( :Sys_User, :PASSWD) ');
Add('from employee');
Add('group by name, getName( :Sys_User, :PASSWD) ');
ParamByName('Sys_User').As String := 'Tom';
ParamByName('PASSWD').AsSt ring := 'dd';
Open
end;
So I wonder if the mistake is caused by using package method of Oracle. There is a package method in groupby clause of first sql statement. So that Delphi5 can't execute it. How to solve it? If I can't assign parameter by ParamByName method, and have to assign parameter value manually?
Please advise. Thanks a lot.
with Query1, SQL do begin
close;
clear;
Add('select ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD
Add('from TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD
ParamByName('PASSWD').AsSt
ParamByName('SYS_USER').As
Open;
end;
Moreover, I try to imitate a similar SQL statement. It can work normally.
with Query2, SQL do begin
Close;
Clear;
Add('select name, getName( :Sys_User, :PASSWD) ');
Add('from employee');
Add('group by name, getName( :Sys_User, :PASSWD) ');
ParamByName('Sys_User').As
ParamByName('PASSWD').AsSt
Open
end;
So I wonder if the mistake is caused by using package method of Oracle. There is a package method in groupby clause of first sql statement. So that Delphi5 can't execute it. How to solve it? If I can't assign parameter by ParamByName method, and have to assign parameter value manually?
Please advise. Thanks a lot.
ASKER
Thanks for your concern.
Since I want to develop a Query Tool, where the user can build sql clause and execute it for displaying the query result.
Since I want to develop a Query Tool, where the user can build sql clause and execute it for displaying the query result.
May be you must use DISTINCT instead of GROUP BY.
Ivan
Ivan
ASKER
Hello IPCH,
The sql statement is defined according user's selection. So can't use DISTINCT instead of GROUP BY.
Would you kindly suggest?
The sql statement is defined according user's selection. So can't use DISTINCT instead of GROUP BY.
Would you kindly suggest?
well i am not really fit with pl sql but the only difference i was able to find is a missing blank
Add('FSK_PKG.DECRYPT_FIELD ( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
Add('from TENDER ');
compared to
Add('select name, getName( :Sys_User, :PASSWD) ');
Add('from employee');
probably that is your problem.
Add('FSK_PKG.DECRYPT_FIELD
Add('from TENDER ');
compared to
Add('select name, getName( :Sys_User, :PASSWD) ');
Add('from employee');
probably that is your problem.
a blank in the parameters doesn't matter, sancho
(pl/sql is my primary job)
atleast what i could guess is,
that a pragma in the pl/sql package is missed
(for avoiding mutating tables during the select),
but the ora-00979 does not point to this
meikl ;-)
(pl/sql is my primary job)
atleast what i could guess is,
that a pragma in the pl/sql package is missed
(for avoiding mutating tables during the select),
but the ora-00979 does not point to this
meikl ;-)
well i am sorry i was just trying to find your problem and after this is not in the parameters but between the select list and the from statement ithought it might have an effect some servers are pretty finicking with things like this ... if oracle is not, fine!
but just another hint just as a trial to find a beginning: have you traced what does really arrives at the server?
If the statement you expect to send is correct (and i guess you know that better than i) but the server does not accept it it seems as if the statement you expect to send is not the statement you really send. I have never seen that delphi causes this, but i also can't see where this should happen in your code. So I'd check if there does arrive what you expect, if so recheck it does run in Toad if yes too i'd search in orcle doc's why ...
but just another hint just as a trial to find a beginning: have you traced what does really arrives at the server?
If the statement you expect to send is correct (and i guess you know that better than i) but the server does not accept it it seems as if the statement you expect to send is not the statement you really send. I have never seen that delphi causes this, but i also can't see where this should happen in your code. So I'd check if there does arrive what you expect, if so recheck it does run in Toad if yes too i'd search in orcle doc's why ...
ASKER
Hi Sfock,
The first sql statement can run in Toad. like below:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
As far the transfer, I think the oracle server accepted the statement expected of Delphi5 generation. You can make references about the trace log #9 of SQL Monitor:
1 09:32:16 Log started for: Delphi 5
2 09:32:22 Log started for: Project1
3 09:32:28 SQL Prepare: ORACLE - select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :1, :2, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :3, :4, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
4 09:32:28 SQL Data In: ORACLE - Param = 1, Name = , Type = fldZSTRING, Precision = 7, Scale = 0, Data = SM2-CLM
5 09:32:28 SQL Data In: ORACLE - Param = 2, Name = , Type = fldZSTRING, Precision = 4, Scale = 0, Data = TEST
6 09:32:28 SQL Data In: ORACLE - Param = 3, Name = , Type = fldZSTRING, Precision = 7, Scale = 0, Data = SM2-CLM
7 09:32:28 SQL Data In: ORACLE - Param = 4, Name = , Type = fldZSTRING, Precision = 4, Scale = 0, Data = TEST
8 09:32:28 SQL Transact: ORACLE - Set autocommit on/off
9 09:32:28 SQL Execute: ORACLE - select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( ?, ?, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( ?, ?, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
10 09:32:28 SQL Error: ORACLE - ORA-00979: not a GROUP BY expression
11 09:32:28 SQL Error: ORACLE - Unmapped SQL Error Code: 979
12 09:32:28 SQL Stmt: ORACLE - Reset
13 09:32:29 SQL Data In: ORACLE - Rows affected = 0
14 09:32:29 SQL Stmt: ORACLE - Close
So I wonder if Delphi5 can't assign valid parameter values to the parameters of groupby clause?
The first sql statement can run in Toad. like below:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
As far the transfer, I think the oracle server accepted the statement expected of Delphi5 generation. You can make references about the trace log #9 of SQL Monitor:
1 09:32:16 Log started for: Delphi 5
2 09:32:22 Log started for: Project1
3 09:32:28 SQL Prepare: ORACLE - select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :1, :2, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :3, :4, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
4 09:32:28 SQL Data In: ORACLE - Param = 1, Name = , Type = fldZSTRING, Precision = 7, Scale = 0, Data = SM2-CLM
5 09:32:28 SQL Data In: ORACLE - Param = 2, Name = , Type = fldZSTRING, Precision = 4, Scale = 0, Data = TEST
6 09:32:28 SQL Data In: ORACLE - Param = 3, Name = , Type = fldZSTRING, Precision = 7, Scale = 0, Data = SM2-CLM
7 09:32:28 SQL Data In: ORACLE - Param = 4, Name = , Type = fldZSTRING, Precision = 4, Scale = 0, Data = TEST
8 09:32:28 SQL Transact: ORACLE - Set autocommit on/off
9 09:32:28 SQL Execute: ORACLE - select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( ?, ?, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( ?, ?, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
10 09:32:28 SQL Error: ORACLE - ORA-00979: not a GROUP BY expression
11 09:32:28 SQL Error: ORACLE - Unmapped SQL Error Code: 979
12 09:32:28 SQL Stmt: ORACLE - Reset
13 09:32:29 SQL Data In: ORACLE - Rows affected = 0
14 09:32:29 SQL Stmt: ORACLE - Close
So I wonder if Delphi5 can't assign valid parameter values to the parameters of groupby clause?
SQL does not accept field names as parameters, which is what you are trying to do in this group by clause. I am not familiar with oracle, but it would be a serious safety loophole to leave.
In DB2 I would do this:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )) as PKG
from TENDER
group by
TEN_ID,
PKG
In DB2 I would do this:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )) as PKG
from TENDER
group by
TEN_ID,
PKG
ASKER
Hi, swift99,
Oracle can't group by field alias such as PKG. Once the alise isn't same to one field name. Then warn ORA-00904: invalid column name.
Oracle can't group by field alias such as PKG. Once the alise isn't same to one field name. Then warn ORA-00904: invalid column name.
:o( Too bad.
try group by 1,2
in SQL92 parlance this means group by the 1st and 2nd columns, independent of their names.
try group by 1,2
in SQL92 parlance this means group by the 1st and 2nd columns, independent of their names.
more guessing,
if the bde is used,
the bde cannot handle packages
move your procedure/function out of the package
as standalone procedure/function
and try again
btw. a group by caluse is not needed anyway,
by this sample selects
meikl ;-)
if the bde is used,
the bde cannot handle packages
move your procedure/function out of the package
as standalone procedure/function
and try again
btw. a group by caluse is not needed anyway,
by this sample selects
meikl ;-)
ASKER
Hello swift99,
Do you try "group by 1,2" in Oracle? I can't run it. Oracle will warn ORA-00979: not a GROUP BY expression. For SQL-92 parlance, can you provide url to introduce the details?
Do you try "group by 1,2" in Oracle? I can't run it. Oracle will warn ORA-00979: not a GROUP BY expression. For SQL-92 parlance, can you provide url to introduce the details?
ASKER
In the group by clause, add tender.ten_id and tender.est_ten_val in the front as below:
Add('TENDER."TEN_ID", ');
Add('TENDER."EST_TEN_VAL", ');
Add('FSK_PKG.DECRYPT_FIELD ( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
The SQL statement can work.
Add('TENDER."TEN_ID", ');
Add('TENDER."EST_TEN_VAL",
Add('FSK_PKG.DECRYPT_FIELD
The SQL statement can work.
I'm not an Oracle person, and don't have oracle available. SQL-92 is the "standard" or vanilla SQL that most servers extend, so it should always be more limited than whatever vendor-specific implementations are there.
I may be surprised, the "group by 1,2" may be a DB2ism. DB2 is as vanilla as it gets syntax wise, but this maybe a syntax that is unique to IBM. I'll look around for some URL's.
I may be surprised, the "group by 1,2" may be a DB2ism. DB2 is as vanilla as it gets syntax wise, but this maybe a syntax that is unique to IBM. I'll look around for some URL's.
ASKER
Hello swift99,
Thanks for your kindness. Waiting for yours.
Thanks for your kindness. Waiting for yours.
ASKER
Hello swift99,
Thanks for your kindness. Waiting for yours.
Thanks for your kindness. Waiting for yours.
ASKER
Hello everybody,
I understand the clause of SQL error. If I want to group by the expression(including params) by Delphi5 like:
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
The expression related to two practical fields. ie. TENDER.TEN_ID and TENDER.EST_TEN_VAL. So I must group by them at the same time. The SQL statement can work by Delphi5. But I didn't know why Toad can run original statement smoothly. If BDE of Delphi5 can't support the groupby statement(need to assign params)?
Please note if use param value insteal of param name, the original statement can run by Delphi like:
with Query1, SQL do begin
close;
clear;
Add('select ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD ( 'SM2-CLM', 'TEST' TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
Add('from TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD ( 'SM2-CLM', 'TEST' TENDER.TEN_ID, TENDER.EST_TEN_VAL )');
Open;
end; {with}
In order by invoke the error. We can use subqueries in from clause.
with Query1, SQL do begin
close;
clear;
Add('select TEN_ID, EST_TEN_VAL ');
Add('from (select TENDER."TEN_ID", ');
Add('FSK_PKG.DECRYPT_FIELD ( :SYS_USER, :PASSWD TENDER.TEN_ID, TENDER.EST_TEN_VAL ) "EST_TEN_VAL"');
Add('from TENDER) TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('EST_TEN_VAL');
ParamByName('PASSWD').AsSt ring := 'TEST';
ParamByName('SYS_USER').As String := 'SM2-CLM';
Open;
end; {with}
Please advise!
I understand the clause of SQL error. If I want to group by the expression(including params) by Delphi5 like:
(FSK_PKG.DECRYPT_FIELD( :SYS_USER, :PASSWD, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
The expression related to two practical fields. ie. TENDER.TEN_ID and TENDER.EST_TEN_VAL. So I must group by them at the same time. The SQL statement can work by Delphi5. But I didn't know why Toad can run original statement smoothly. If BDE of Delphi5 can't support the groupby statement(need to assign params)?
Please note if use param value insteal of param name, the original statement can run by Delphi like:
with Query1, SQL do begin
close;
clear;
Add('select ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD
Add('from TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('FSK_PKG.DECRYPT_FIELD
Open;
end; {with}
In order by invoke the error. We can use subqueries in from clause.
with Query1, SQL do begin
close;
clear;
Add('select TEN_ID, EST_TEN_VAL ');
Add('from (select TENDER."TEN_ID", ');
Add('FSK_PKG.DECRYPT_FIELD
Add('from TENDER) TENDER ');
Add('group by ');
Add('TEN_ID, ');
Add('EST_TEN_VAL');
ParamByName('PASSWD').AsSt
ParamByName('SYS_USER').As
Open;
end; {with}
Please advise!
BDE implements a subset of SQL. Unless you make it otherwise, it takes your SQL, interprets it, and builds new SQL to pass on to the back end.
Options:
1. Set the BDE components to "pass through" the SQL. I believe that it is a setting on the TDatabase component.
2. Switch to CLX components which do not have the overheads (or interference) of the intermediate interpreter. There is a CLX DLL for Oracle, so that should work okay.
Options:
1. Set the BDE components to "pass through" the SQL. I believe that it is a setting on the TDatabase component.
2. Switch to CLX components which do not have the overheads (or interference) of the intermediate interpreter. There is a CLX DLL for Oracle, so that should work okay.
ASKER
Hello swift99,
Can you introduce some CLX components and show some examples?
Can you introduce some CLX components and show some examples?
ASKER
For #1 of Options:
If I can deploy TDatabase.TransIsolation property? Please advise.
If I can deploy TDatabase.TransIsolation property? Please advise.
Pass-through SQL for BDE components - I see it exists in various Delphi online help, but no examples. I am using DB2 API directly most of the time so I don't have these middle pieces except for simple applications.
CLX components - Use SQLConnection instead of TDatabase, and SQLQuery instead of TQuery.
Usage is remarkably similar to BDE components. You have one or two less layers of abstraction between you and the DBMS, so you will need to be aware of the limits and characteristics of the DBMS. At this level you don't have the bidirectional buffering that the BDE builds for you so if you need interactive scrolling you will want to use a client dataset.
About the Oracle trace you posted earlier:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :1, :2, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :3, :4, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
Note that Oracle is expecting a third and fourth parameter - I bet BDE is only providing two.
Also, from the online Delphi manual:
Note: Some SQL database systems require strict case-sensitivity for names of metadata objects in SQL statements. These SQL databases typically have problems with the way metadata names are passed by the BDE in live queries and an exception is raised. A workaround that helps in most cases is to enclose the metadata object references (like table and column names) in quotation marks.
CLX components - Use SQLConnection instead of TDatabase, and SQLQuery instead of TQuery.
Usage is remarkably similar to BDE components. You have one or two less layers of abstraction between you and the DBMS, so you will need to be aware of the limits and characteristics of the DBMS. At this level you don't have the bidirectional buffering that the BDE builds for you so if you need interactive scrolling you will want to use a client dataset.
About the Oracle trace you posted earlier:
select
TEN_ID,
(FSK_PKG.DECRYPT_FIELD( :1, :2, TENDER.TEN_ID, TENDER.EST_TEN_VAL ))
from TENDER
group by
TEN_ID,
FSK_PKG.DECRYPT_FIELD( :3, :4, TENDER.TEN_ID, TENDER.EST_TEN_VAL )
Note that Oracle is expecting a third and fourth parameter - I bet BDE is only providing two.
Also, from the online Delphi manual:
Note: Some SQL database systems require strict case-sensitivity for names of metadata objects in SQL statements. These SQL databases typically have problems with the way metadata names are passed by the BDE in live queries and an exception is raised. A workaround that helps in most cases is to enclose the metadata object references (like table and column names) in quotation marks.
ASKER
Dear swift99,
If it's convenient for you, can you show a sample for using DB2 API?
If you know any URL resources to introduce CLX, please list. Thanks.
If it's convenient for you, can you show a sample for using DB2 API?
If you know any URL resources to introduce CLX, please list. Thanks.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank all for the helps.
why you use a group by clause,
there is no aggregate-field in your select
meikl ;-)