2

I am trying to get the query result from the Oracle sql server and insert it in the StringGridShowPapers table.

I have SQLConnection1 (a DBExpress connection) set up and working, SQLDataSetPapers DataSet and a query SQLQueryPapers.

When I am running this procedure, the query seems to return nothing:

procedure TFormOperator.TabSheetShowPapersShow(Sender: TObject);
begin
    SQLQueryShowPapers.SQL.Text := 'SELECT * FROM papers';
    SQLQueryShowPapers.Open;
    SQLQueryShowPapers.First;

    if (NOT SQLQueryShowPapers.IsEmpty) then begin
        SQLQueryShowPapers.First;
        StringGridShowPapers.RowCount := 2;

        while (NOT SQLQueryShowPapers.EOF) do begin
            if (SQLQueryShowPapers.Fields[2].AsString = Frame11.ID) then begin
                with StringGridShowPapers do begin
                  Cells[0, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[0].AsString;
                  Cells[1, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[1].AsString;
                  Cells[2, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[2].AsString;
                end;
                SQLQueryShowPapers.Next;
                StringGridShowPapers.RowCount := StringGridShowPapers.RowCount + 1;
            end;
        end;
    end;

end;

Frame11.ID contains a string value of a number.

Running the same query SELECT * FROM papers in oracle SQL Developer results a number of rows.

What could trigger the problem?

Thanks in advance!

Looks like i found the solution:

It looks like the some (global) variables and properties in Delphi are inaccessable or simply cleaned up after the procedure that assigns them is finished. So you may need to assign first form value to a global variable of second one (that you use this value in) in a runtime of the first form procedure.

7
  • SQLQueryShowPapers.Next; is inside IF BEGIN... END . you need move it out from the IF Commented Jul 8, 2017 at 12:07
  • @are thanks for noticing this! But the problem still didn't go Commented Jul 8, 2017 at 12:16
  • I am not even getting into first condition Commented Jul 8, 2017 at 12:20
  • IsEmpty was buggy at some time. You may use if not (Query.Bof and Query.Eof) then. Except that, move that Next call outside the if block and remove both First calls. Commented Jul 8, 2017 at 13:06
  • @Victoria, thanks, i've changed the condotion, but the problem still exists Commented Jul 8, 2017 at 13:43

2 Answers 2

3

You have a couple of flaws in your code.

First, you don't need IsEmpty, and you don't need either call to First. When you first open a query, the dataset is automatically set at the first row, and you can omit IsEmpty if you know you're going to iterate over the rows.

Second, you should never SELECT without a WHERE clause and then filter the data afterward. The only reason to SELECT without a WHERE is if you're absolutely certain you need every single row (and column) from the table. If you don't, add a WHERE in order to limit the number of rows that are returned from the server (and to avoid having to write so much code to filter it on the client side).

Try something like this instead. I don't know what datatype Fields[2] or Frame11.ID are, so I'm going to treat them as string as your existing code does. If they're not strings, then change both references to the actual data type needed. I'm also going to presume that Fields[2].FieldName is ID; again, if it's not, change the code accordingly.

procedure TFormOperator.TabSheetShowPapersShow(Sender: TObject);
var
  GridRow: Integer;
begin
  SQLQueryShowPapers.SQL.Text := 'SELECT * FROM papers WHERE ID = :ID';
  SQLQueryShowPapers.Parameters.ParamByName('ID').Value := Frame11.ID;
  SQLQueryShowPapers.Open;  // No need for First. Happens automatically

  StringGridShowPapers.RowCount := 1;

  // No need for IsEmpty. If no rows were returned, this loop will not be entered
  while not SQLQueryShowPapers.EOF do
  begin
    StringGridShowPapers.RowCount := StringGridShowPapers.RowCount + 1;
    GridRow := StringGridShowPapers.RowCount - 1;

    StringGridShowPapers.Cells[0, GridRow] := SQLQueryShowPapers.Fields[0].AsString;
    StringGridShowPapers.Cells[1, GridRow] := SQLQueryShowPapers.Fields[1].AsString;
    StringGridShowPapers.Cells[2, GridRow] := SQLQueryShowPapers.Fields[2].AsString;
    SQLQueryShowPapers.Next;
  end;
end;

As an aside, I'd do a couple of things:

  • Most importantly, stop using SELECT * and actually list the columns you need. It's easier to maintain the code, and it reduces overhead of moving data from the server across the network that you're not going to use.

  • Also, stop using hard-coded references to field positions (Fields[0], Fields[1], etc.). It's error prone, it will bite you in the backside when a column changes in the future, and it makes the code impossible to maintain 6 months from now when you don't remember exactly what order the columns are in or someone else needs to work with your code. Either add persistent fields to your query or use FieldByName to retrieve them by name.

  • Shorten the variable names to avoid typing somewhat. SQLQueryShowPapers, for instance, could just be QryPapers (unless you have some other type of query than a SQL query, that is), and StringGridShowPapers could be GridPapers or PaperGrid.

  • You'll note I added a local integer variable GridRow to reduce the typing required for all the repeated calls to StringGridShowPapers.RowCount - 1 in every access to Cells.

  • You'll also note I made it simpler to deal with adding new rows to StringGridShowPapers in the loop.

  • I also removed the need to test Fields[0].AsString = Frame11.ID by adding a parameter and a WHERE clause to your SQL statement. It also reduces the amount of data that has to pass from the server across the network, reduces the memory requirements of your application, and cuts the amount of time you spend unnecessarily reading rows you won't be using and skipping them (iterations through the loop). In other words, I removed the entire if test.

  • Lastly, you could reduce this entire code down to three lines (setting the SQL.Text, assigning a value to the parameter, and opening the query) if you got rid of the TStringGrid entirely and used a TDBGrid instead. It's specifically designed to display data from a dataset. All you do is add the TDBGrid to your form in place of the TStringGrid, drop a TDataSource as well, connect the TDBGrid.DataSource to theTDataSourceand theTDataSource.DataSet` to your query. Then open your query as usual, and the grid is automatically populated with the data with zero lines of code.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for advices!) Will do so
0

try this, the next operator is out of if block I think something in your data doesn't let you cycle to be completed

procedure TFormOperator.TabSheetShowPapersShow(Sender: TObject);
begin
    SQLQueryShowPapers.SQL.Text := 'SELECT * FROM papers';
    SQLQueryShowPapers.Open;
    SQLQueryShowPapers.First;

    if (NOT SQLQueryShowPapers.IsEmpty) then begin
        SQLQueryShowPapers.First;
        StringGridShowPapers.RowCount := 2;

        while (NOT SQLQueryShowPapers.EOF) do begin
            if (SQLQueryShowPapers.Fields[2].AsString = Frame11.ID) then begin
                with StringGridShowPapers do begin
                  Cells[0, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[0].AsString;
                  Cells[1, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[1].AsString;
                  Cells[2, (StringGridShowPapers.RowCount - 1)] :=
                    SQLQueryShowPapers.Fields[2].AsString;
                end;
                StringGridShowPapers.RowCount := StringGridShowPapers.RowCount + 1;
            end;
             SQLQueryShowPapers.Next;
        end;
    end;

end;

1 Comment

did that, still same empty query output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.