How do you use the SQLQuery component to run multiple queries? - database

I have a ListBox showing all the records for a single field (first) in a database. When users click the ListBox item I'd like the value for a different field in the db (last), same record, to be displayed. My code ListBox OnClick event code is:
SQLQuery2.SQL.Text:='SELECT * FROM Names WHERE first= :FIRST';
SQLQuery2.Params.ParamByName('FIRST').AsString := ListBox1.Items[ListBox1.ItemIndex];
SQLQuery2.Open;
ShowMessage('You selected '+SQLQuery2.FieldByName('last').AsString);
When you click an item, the expected field comes up in the MessageBox. However, if you then click a different item, nothing changes--the MessageBox shows the original field.
I don't know enough about SQLQuery components and how they interact with the underlying db to know what's happening.
[P.S. The db is sqlite3, if that matters, and I'm using Lazarus rather than Delphi, if that matters.]

You need to close your query before opening it again. If you look at the code for Open on TDataSet it sets the Active property to true. The setting code for Active first checks that the value is different before doing any work:
procedure TDataSet.SetActive(Value: Boolean);
begin
..
if Active <> Value then
begin
end;
end;
So in your case, the active property is already true and the code just exits.

Related

Connect multiple tables in Access

I want to connect multiple tables in Access. I have a main table and then multiple smaller tables that I would like to connect. Each row in the main table belongs to one entire sub-table. I would like to have small + appear next to each row in the main table and showing the sub-tables upon clicking on the +.
I tried this via relationships but it only works for the first row (perfectly) but not for any other rows. When clicking on the other rows, they are empty and no sub-table is opening up.
Any ideas?
Per the comments if you must do this here is an example:
example main table and sub tables
example form created from the main table using the create form wizard and selecting tabular to get a better looking starting form:
note I added an unbound button to the details section and that button gets replicated for each row of data. I will show two ways of setting up the button to open the correct form.
put the form in design mode open the button's properties and open the onclick event. you can do this with the macro language but I show the code:
Private Sub openButton_Click()
'each button the detail section creates has access to the data or controls in the buttons row
DoCmd.OpenTable Me.subTableName 'if form use .OpenForm
'DoCmd.Close acForm, "mainForm" 'if want to close main form
'OpenTable (MainID)
End Sub
if the logic behind opening the form gets complicated I suggest abstracting the logic to a function. here use OpenTable instead and add the Public OpenTable function inside a code module.
Public Function OpenTable(tableID As Long) As Boolean 'function allows the option checking the return value to test if OpenTable worked
Select Case tableID
Case 1
DoCmd.OpenTable "subTable1"
Case 2
DoCmd.OpenTable "subTable2"
Case 3
DoCmd.OpenTable "subTable3"
End Select
OpenTable = True
End Function
Note: you could expand the form's header and show the mainTable as a subform in that header. Then you could add a button next to each row in that subform but outside the subform. The approach I show is easier to maintain.

How can I populate a combobox from a SQL Server database server in Delphi?

First of all, I'm new to Delphi, and I checked all the relevant threads on here, but nothing seems to be working.
I'm just trying to fill a TComboBox with values of a column from a SQL Server database.
So basically, I have a VCL form and a DataModule, which holds an ADOConnection and an ADOQuery. The ADOConnection connects to my database (test connection says it's successful) and the ADOQuery connects to my ADOConnection. The VCL form and the DataModules are "connected".
(And actually here comes another problem: whenever I'm trying to enter SELECT name FROM Partners; in the properties of my ADOQuery and try to set it active, it keeps saying "Invalid object name 'Partners'". The SQL statement is correct, I tested it in SSMS and it retrieves the data without any error. But I'm not sure if it's the main issue here).
So basically, here's my code:
procedure TFormInsertNewItem.ComboBoxPartnersDropDown(Sender: TObject);
begin
with DataModule1 do
begin
ComboBoxPartners.Items.Clear;
ADOQueryFillPartners.SQL.Clear;
ADOQueryFillPartners.SQL.Add('SELECT name FROM Partners;');
ADOQueryFillPartners.Active:=true;
ADOQueryFillPartners.Open;
while not ADOQueryFillPartners.Eof do begin
ComboBoxPartners.Items.Add(ADOQueryFillPartners.FieldByName('name').AsString);
ADOQueryFillPartners.Next;
end;
ADOQueryFillPartners.Active:=false;
ADOQueryFillPartners.Free;
end;
end;
Whenever I click to drop it down (or maybe it would be better if this runs when the form is loaded, but I have no idea how can I exactly refer to that event), it should fill it up. Well, it won't. I tried it with TDBComboBox and TDBLookUpComboBox, with setting their datasource, but it only added 1 item to the combobox.
Can anyone help me with what I messed up and how can I get it to work, please?
You have multiple problems in the code you've posted.
Clearly, the first thing you have to do is to get your query to open properly. If you can't run the query to get the data, you can't use that data to populate the combobox. Test your ADOConnection on your datamodule to see if you can connect to the database by setting its Connected property to True.
If that doesn't work, then you need to set up your ConnectionString properly. (Make sure you set the Connected property back to False. You should be connecting in your datamodule's OnCreate event, and disconnecting in the datamodule's OnDestroy event.)
If it does work, check to make sure you set the ADOQuery's Connection property to point to your ADOConnection, and then use the ADOQuery.SQL property to enter your SQL statement. Once you've done that, set the ADOQuery.Active property to True. (Again, don't forget to set it back to False and open it in your code at runtime.)
Next, you've used the wrong event. You should be doing this in the form's OnCreate event instead.
Also, you don't need both Active and Open for the query. They do the same thing; the only difference between them is that Active is a Boolean property that can be tested (if Query1.Active then) while Open is simply a method. There's no reason to open a query that's already active or make a query active that's already open.
In addition, you free the query at the end of your method, which means that the next time the combobox OnDropDown event is called, you're accessing an invalid class instance, which will cause an access violation.
And finally, you should be calling BeginUpdate before clearing and populating the combobox, and then EndUpdate when you're finished.
A more correct version of the code would be something like
procedure TFormInsertNewItem.FormCreate(Sender: TObject);
begin
with DataModule1 do
begin
{
I'm not sure why you're doing this at all. If you set the ADOQuery.SQL property
at designtime, and it never changes, you can remove the next two lines.
}
ADOQueryFillPartners.SQL.Clear;
ADOQueryFillPartners.SQL.Add('SELECT name FROM Partners;');
ADOQueryFillPartners.Active:=true;
try
ComboBoxPartners.Items.BeginUpdate;
while not ADOQueryFillPartners.Eof do begin
ComboBoxPartners.Items.Add(ADOQueryFillPartners.FieldByName('name').AsString);
ADOQueryFillPartners.Next;
end;
finally
ComboBoxPartners.Items.EndUpdate;
end;
ADOQueryFillPartners.Active:=false;
end;
end;

SSIS Logging - Capture Variables?

I'm trying to capture the values of about 15 variables within my sysssislog when my package executes.
I have set all the variables to true for "Raise event when variable value changes" and I understand I have to put some sort of object/code into the Event handler but I'm totally unsure as to what this should look like for the 15 variables.
Can anyone offer some examples please?
After the RaiseChangedEvent property is set to true on the variable the OnVariableValueChanged event will need be selected for logging to SYSSSISLOG. This can be done by right-clicking the package and selecting Logging then going to the Details tab and checking the check-box for the OnVariableValueChanged event. After this click the Advanced button and check the box for each element that will be logged, for instance Computer, SourceName, etc. To see the actual value that the variable was changed to query the SSISDB.CATALOG.EVENT_MESSAGES DMV following package execution. The MESSAGE column will show the value that the variable was set as during package execution.

How to force update a DB grid?

I may have been too clever for my own good :-/
I have a table which holds some pressure measurements. These are always stored as PSI, but the user can select a radio group button to toggle between PSI and BAR.
In order to keep the code clean and and push work onto the database, I created a second table for configuration items, with a single row. One column psi_bar_conversion will take the value either 1 or 14.5 as the user toggles the radio group.
In Delphi, my query which ties to my DB grid is set up with statements like
SELECT ROUND(inlet_waterPressure_psi /
(SELECT psi_bar_conversion FROM configuration),
(SELECT float_precision FROM configuration))
AS inlet_waterPressure,
FROM measurements
All of which works just fine (and perhaps I am explaining too much).
All that I am tring to do is add some code in the function which handles the radio button toggle to force my DB grid to refresh its contents becuase I have just updated the value of configuration.psi_bar_conversion (but no direct field of my query, nor of my datasource).
Should I invoke Refresh() or Invalidate() or SomeOtherFunction() - of the DB grid, the query, the datasrouce? That's what is confusing me.
Thanks in advance for any help ....
You need to close and then reopen the query to have the change in psi_bar_conversion and float_precision to take effect. The two sub-selects (for the values from configuration) only happen when the query is executed.
TDBGrid presentation depends on the connected TDataSet (via a TDataSource).
To update the Grid Values you have to refresh the data in TDataSet with the method TDataSet.Refresh.
To update a special Grid you can refresh the connected DataSet like this:
DBGrid1.DataSource.DataSet.Refresh;
But some TDataSet descendants will not refresh and that is documented by Embarcadero
TDataSet.Refresh
It depends on the components you use (i did a test with UniDAC and it works fine)
procedure TForm1.RadioGroup1Click( Sender : TObject );
var
LRate : Extended;
begin
case RadioGroup1.ItemIndex of
0 :
LRate := 1;
1 :
LRate := 14.5;
end;
UniConnection1.ExecSQL( 'UPDATE configuration SET psi_bar_conversion = :conversion', [LRate] );
DBGrid1.DataSource.DataSet.Refresh;
end;
If your components did not refetch the data on calling Refresh, then you have to close and reopen (also stated by documentation)
DBGrid1.DataSource.DataSet.Close;
DBGrid1.DataSource.DataSet.Open;
IMHO such components are not fully implemented, so this is just a workaround having side effects in calling some maybe unwanted events (BeforeClose, AfterClose, BeforeOpen, AfterOpen) which will not get fired using Refresh.
But at all it has nothing to do with SubSelects.
I'm afarid I can't help you with the Delphi side of things here.
On the datbase side of things....
Is there any reason that you can't just store both the bar and psi values in the database?
You could do the conversion when saving and then you are left just to do a simple select on the data when you want to view it. This could be done by the software that is performing the save or by a trigger in the database.
The reason I suggest this is that the psi-bar conversion ratio is not going to change so you are doing a bunch of processing everytime you view the data that is not required...

Updating a grid after changes have been made

Right, this is probably going to be pretty simple. I have a form that contains a grid, if you select one of the records and press 'Edit' you get taken to another form where you can edit the data attached to that record - this all works.
However upon saving it will write it to the database but will not update the aforementioned grid until I come out of my program all together and then go back in.
All I want to do is get the grid to update when exiting the other form.
I have tried opening/closing the table components, calling the 'refresh' against the query and the table. I am connecting to the database using BDE and writing this in Rad Studio XE2.
Any help would be appreciated.
Hope this solves your problem
Table1.Active := False;
Table1.Active := True;
for a TTable and
TQuery1.Active := False;
TQuery1.active := True;
for a TQuery

Resources