I have a long SQL text that I want to assign to a query SQL. I do this the following way:
SQL.Text:= 'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,'+
' T1.COLUMNn FROM TABLE1 T1 INNER JOIN '+
' TABLE2 T2 ON T1.ID=T2.ID'+
' WHERE T1.COLUMN10=100'
The actual SQL is 20 times longer than this. My problem is with the line breaks. When I format the source code (Ctrl+D) it sometimes leaves the lines as I typed, but other times it deletes the line breaks and I get something like this:
'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3 ' + 'FROM TABLE1 T1 INNER JOIN '+ 'TABLE2 T2 ON T1.ID=T2.ID'
And this leads to a "line too long (more than 1023 charactes)" error. What's interesting is this does not happen with all lines. I can't catch the difference between the lines which will be affected and those that won't. I need a line break after or before the "+" sign. How do I do this?
You can also use the Add function.
SQL.Clear;
SQL.ADD('SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,');
SQL.ADD(' T1.COLUMNn FROM TABLE1 T1 INNER JOIN');
SQL.ADD(' TABLE2 T2 ON T1.ID=T2.ID');
SQL.ADD(' WHERE T1.COLUMN10=100');
Try to assign the value in every line:
SQL.Text := 'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,';
SQL.Text := SQL.Text + ' T1.COLUMNn FROM TABLE1 T1 INNER JOIN ';
SQL.Text := SQL.Text + ' TABLE2 T2 ON T1.ID=T2.ID';
SQL.Text := SQL.Text + ' WHERE T1.COLUMN10=100';
I know it looks ugly, but I think it solves your problem.
Related
I have a grid that connected to AdoDataset. i want read records from two table with join SQL, but save record in a table.
Read data:
adodataset.commandtext := 'select * from Table1 left join Table2 on Table1.ID = Table2.ID';
adodataset.Open;
I want save Table1 Fields only when post
You can use ReadOnly property of DBGrid.Columns. For example if you have a query like this:
ADODataSet1.CommandText := 'SELECT * FROM Table1 JOIN Table2 ON Table1.ID = Table2.ID';
Then your DBGrid will be like:
You can then make 3rd and 4th columns read only at design time or at run time by these codes:
DBGrid1.Columns[2].ReadOnly := True;
DBGrid1.Columns[3].ReadOnly := True;
Also note that if you want to delete records only from Table1 then you should run this code when ADODataSet1 is active:
ADODataSet1.Properties['Unique Table'].Value := 'Table1';
Update:
As suggested in comments it's a good idea to set desired fields ReadOnly at DataSet level:
ADODataSet1.FieldByName('ID_1').ReadOnly := True;
ADODataSet1.FieldByName('Table2_Value').ReadOnly := True;
First of all the query example in the commandtext is wrong / ambiguous. I don't know what you want to perform but I'm guessing you want to change/save data in a table. In this case, why don't you perform the update in sql? Let's say you have the primary key field called "id", and you want to save a field called "name" with another value.
var
id, NewName: string;
//...
begin
//...
id := adodataset.fieldbyname('id').AsString;
adodataset.connection.execute(
'UPDATE table1 SET name = ' + quotedstr(NewName) + ' WHERE id = ' + quotedstr(id)
);
// refresh the records by closing and reopening the adodataset
adodataset.close;
adodataset.open;
// move to the wanted record
adodataset.Locate('id', id, []);
Why not use TAdoQuery ?
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Add("select * from Table1 left join Table2 on Table1.ID = Table2.ID");
Qry.Open;
while not Qry.EOF do
begin
[do stuff]
Qry.Next;
end;
I am getting incorrect count from a query ran inside a stored procedure.
When we run the same query ( after hard-coding the values of table name and schema name ) it gives the correct result.
Preliminary analysis , hints the fact that the query run inside the stored procedure is for some reason ignoring the second filter ( i.e where ... and ... , the second part is being ignored ).
CREATE OR REPLACE PROCEDURE dev.gp_count (tablename VARCHAR(256))
AS
$$ DECLARE schema_name VARCHAR(64);
table_name VARCHAR(128);
check_count_1 INT;
check_count_2 INT;
BEGIN
schema_name:= SPLIT_PART(tablename,'.',1);
table_name:= SPLIT_PART(tablename,'.',2);
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' + table_name +'%');
raise info 'check_count_1 - %',check_count_1;
end;
$$
language plpgsql;
And calling the above procedure as-
call dev.gp_count ('dev.gp_test1');
The result obtained from stored procedure is -
Warnings:
check_count_1 - 925
If we run the same query after substituting the values for table name and schema then -
select count(*) from information_schema.tables where table_schema = 'dev' and table_name like '%gp_test1%';
RESULT -
count
3
Now investigating the issue further -
The count obtained from stored procedure is same as the count obtained from this query -
select count(*) from information_schema.tables where table_schema = 'dev';
RESULT-
count
925
My Guess -
So this hints that , maybe inside stored procedure the second filter condition is being ignored.
Besides helping me with other alternatives , please do help me find the reason behind this anomaly too .
Thanks in Advance.
I think your problem lies in 1) your string concatenation and 2) use of table_name as a variable:
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' + table_name +'%');
PostgreSQL string concatenation uses ||, so it should look like this:
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' || table_name || '%');
Try changing it to look like this:
CREATE OR REPLACE PROCEDURE gp_count (tablename VARCHAR(256))
AS
$$ DECLARE
schema_name VARCHAR(64);
table_name1 VARCHAR(128);
check_count_1 INT;
check_count_2 INT;
BEGIN
schema_name:= SPLIT_PART(tablename,'.',1);
table_name1:= SPLIT_PART(tablename,'.',2);
check_count_1 := (select count(*) from information_schema.tables f where table_schema = schema_name and f.table_name like '%' || table_name1 || '%');
raise info 'check_count_1 - %',check_count_1;
end;
$$
language plpgsql;
Disclosure: I work for EnterpriseDB (EDB)
I'm using Delphi 7 with ADO components, and MS Access 2003. The SQL sentence
SELECT CMCB.Name,
(SELECT SUM(amount) FROM movement MCB
WHERE MCB.movement_classification_id=CMCB.movement_classification_id
AND MCB.operation_date >= #01/01/2013#
AND MCB.operation_date < #01/01/2014#
) AS MyYear
FROM movement_classification CMCB
is working fine in MS Access console but through a Delphi application launches the following error when I am opening the DataSet (TADOQuery):
Data provider or other service returned an E_FAIL status
Any idea why it happens? Is it related with the ADO component (TADOQuery in this case)
I tried a similar query from the database dbdemos.mdb (Program Files\Common Files\Borland Shared\Data) and it works
SELECT CustNo,
(SELECT SUM(AmountPaid) FROM orders O
WHERE O.CustNo = C.CustNo
AND O.SaleDate >= #01/01/1994#
AND O.SaleDate < #01/01/1995#
) AS AmountPaid
FROM customer C
The code I used in Delphi is the following:
procedure TForm1.Button1Click(Sender: TObject);
begin
ADOConnection1.Connected := False;
ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=D:\Xiber\Delphi\StackOverflow\Subquerys\dbdemos.mdb';
ADOConnection1.Connected := True;
ADOQuery1.SQL.Text := 'SELECT CustNo, (SELECT SUM(AmountPaid) FROM orders O WHERE O.CustNo = C.CustNo AND O.SaleDate >= #01/01/1994# AND O.SaleDate < #01/01/1995#) AS AmountPaid FROM customer C';
ADOQuery1.Open;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
sSQL: string;
begin
ADOConnection1.Connected := False;
ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=D:\Xiber\Delphi\StackOverflow\Subquerys\XiGest-CASA.mdb';
ADOConnection1.Connected := True;
sSQL := ' SELECT CMCB.Name, ' +
' (SELECT SUM(amount) FROM movement MCB ' +
' WHERE MCB.movement_classification_id=CMCB.movement_classification_id ' +
' AND MCB.operation_date >= #01/01/2013# ' +
' AND MCB.operation_date < #01/01/2014# ' +
' ) AS MyYear ' +
' FROM movement_classification CMCB ';
ADOQuery1.SQL.Text := sSQL;
ADOQuery1.Open;
end;
As it stands, your query should return the same value for sum(qty) for each row of employee. If Access is "hiding" the relationship between the two tables, that could explain why it works in Access.
I would expect a query something like:
select e.name, sum(i.qty)
from
employee e,
items i
where
i.employeeid = e.employeeid
would be something more like what you're after. This, of course, assumes a direct relationship (the foreign key of employeeid in the items table) between the two tables, which is not very realistic.
As others have commented, more information would permit a more precise answer!
Is there any reason you couldn't simplify the query (assuming it is an ADO bug) such as:
select CMCB.Name, SUM(MCB.amount)
from
movement_classification CMCB,
movement MCB
where
MCB.movement_classification_id=CMCB.movement_classification_id
AND MCB.operation_date >= #01/01/2013#
AND MCB.operation_date < #01/01/2014#
Finally I realised the difference between the two sums was that in dbdemos the field AmountPaid.mdb is double and in my case is decimal(8,2).
It seems to be an ADO bug. You can reproduce by yourself.
So, If you change the field AmountPaid in dbdemos.mdb (provided by Borland, you can found at Program Files\Common Files\Borland Shared\Data) to decimal(8,2) and execute the query through Delphi 7 (with an ADOConnection and an ADOQuery), you'll get the error above mentioned.
SELECT CustNo,
(SELECT SUM(AmountPaid) FROM orders O
WHERE O.CustNo = C.CustNo
AND O.SaleDate >= #01/01/1994#
AND O.SaleDate < #01/01/1995#
) AS AmountPaid
FROM customer C
But if you execute this query inside MS Access, it works fine.
I'm using FastReport4 in DelphiXE4.
I set Connection String at RunTime Like this:
ADOConnection.ConnectionString := ConStr;
ADOConnection.Connected := True;
AdoQuery1.Connection := ADOConnection;
So I cannot see preview in FastReport Designer!
I have a query like this:
AdoQuery.Sql.Text :='SELECT Table1.title,Table2.title FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
I have a problem with Field name in FastReport Designer.
I tested [frxDBDataset1."Table1.title"], but Field Not Found !
Then I changed Query Like This:
AdoQuery.Sql.Text :='SELECT Table1.title as f1,Table2.title as f2 FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
and in FastReport Designer:
[frxDBDataset1."f1"]
But same error occurred!
Solution:
Select frxDBDataset and clear all FieldAliasis then use this:
AdoQuery.Sql.Text :='SELECT Table1.title as f1,Table2.title as f2 FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
And:
[frxDBDataset1."f1"]
I'm using Delphi XE2 with AnyDac Components and Advantage Database 10.
In my code I'm using parametrized querys like this:
q.SQL.Text := 'SELECT * FROM Table1 ' +
'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
'WHERE ' +
':0 BETWEEN Table1.StartAm AND Table1.EndeAm ' +
'AND Table2 = :1';
q.Params[0].Value := AStartDateTime;
q.Params[1].Value := AIDRessourcenGruppe;
q.Open;
this ends up in an exception:
Exception der Klasse EADSNativeException mit der Meldung
'[AnyDAC][Phys][ADS] Error 7200: AQE Error: State = 22018;
NativeError = 2112; [iAnywhere Solutions][Advantage SQL
Engine]Assignment error' aufgetreten.
of course AStartDateTime is a valid delphi TDateTime value, AIDRessourcenGruppe is a integer value.
interestingly, these two variants work:
q.SQL.Text := 'SELECT * FROM Table1 ' +
'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
'WHERE ' +
':0 BETWEEN Table1.StartAm AND Table1.EndeAm ' +
'AND Table2 = :1';
q.Params[0].AsDateTime:= AStartDateTime;
q.Params[1].AsInteger:= AIDRessourcenGruppe;
q.Open;
-
q.SQL.Text := 'SELECT * FROM Table1 ' +
'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
'WHERE ' +
':SomeDate BETWEEN Table1.StartAm AND Table1.EndeAm ' +
'AND Table2 = :ID_PT_Ressourcengruppe';
q.ParamByName('SomeDate').Value := AStartDateTime;
q.ParamByName('ID_PT_Ressourcengruppe').Value := AIDRessourcenGruppe;
q.Open;
Do I miss something? Thanks for any help!
Answer - just a guess:
I would say the indexed write access to Value property of the parameters doesn't determine data type of parameters whilst the named access does. And if that's correct, then you're in trouble because you're passing all the values through Variant type which must converted to a proper value format before the query is performed. But all of that is just my guess - I don't know AnyDAC at all!
AsType value access:
I'm posting this just because I don't like Value access to parameters to be called professional :-)
It's better to use AsType typecast at least because:
it is faster because you directly say what type you're passing to a certain parameter, thus the query parameter engine doesn't need to determine this, and in comparison with Value access, it doesn't need to convert Variant type
it's safer for you, because you can't pass e.g. string value to AsDateTime accessed parameter, so you have an extra protection against parameter mismatch
What I commend in your example, is the use of indexed access to parameters, instead of commonly used named which needs to search the parameter list before the access and which is slower.