Using multiple SQL queries - sql

I have done some searching and can't find a definitive answer to this one.
I am just getting into SQL so be gentle. Using D5, TNTUnicode, Zeos and SQLite3
I have a DBGrid with all the Account names in the tblAccounts showing.
I have a DBGrid with all the Folders in the tblFolders showing.
In the OnCellClick of the Accounts grid I have an SQL query
qryFolders.Close;
qryFolders.SQL.Clear; // Not really needed as I am assigning the Text next - but :)
qryFolders.SQL.Text:=
'SELECT Folder FROM tblFolders WHERE UPPER(Account)="FIRSTTRADER"'
qryFolders.ExecSQL;
tblFolders.Refresh;
In my application, nothing happens, I still have the full list of Folders visible.
In the SQL-Expert desktop that line works fine and displays only the two Folders associated with that Account. In that app it keeps displaying the full list of Folders
If I step through the OnCellClick it shows the correct Text etc.
Where am I going wrong?
Thanks

If you want to display a Master-Detail (Account as Master, Folder as Detail), so we start from here:
// connecting the grids
AccountsDataSource.DataSet := tblAccounts;
AccountsGrid.DataSource := AccountsDataSource;
FoldersDataSource := tblFolders;
FoldersGrid.DataSource := FoldersDataSource;
// retrieving the data
tblAccounts.Open;
tblFolders.Open;
That should reflect, what you already have. Now lets go to the Master-Detail.
It should be obvious that all Query and Table Components have a valid Connection set, so I will left this out.
First be sure, the Query is not active
qryFolders.Active := False;
Having a Master-Detail with a Query as Detail, we have to set the MasterSource
qryFolders.MasterSource := AccountsDataSource;
and after that we can setup the Query with parameters to link to the fields from MasterSource. Linking to the field Account in the MasterSource is done by using :Account
qryFolders.SQL.Text :=
'SELECT Folders FROM tblFolders WHERE UPPER( Account ) = :Account';
Now, we are ready to retrieve the data
qryFolders.Open;
Until this, we will not see any changes in the FoldersGrid, because we didn't told anyone to do so. Now let's get this to work with
FoldersDataSource.DataSet := qryFolders;
In your approach, you didn't Open the Query and you didn't link the Query to the Grid.
Another option is to have a Master-Detail without a separate Query.
(It seems there were some code refactoring, so i guess this is a working sample)
tblFolders.MasterSource := AccountsDataSource;
tblFolders.MasterFields := 'Account';
tblFolders.LinkedFields := 'Account';
Reference:
SourceForge ZTestMasterDetail.pas (see line 181ff)
SourceForge ZDataset.pas

Related

Multiple change of lotus type groups

maybe someone once wrote a script for mass change of lotus type groups? Mass but not all, only grups with first two characters begins on ('GD') i need change mostly type from mail only (3) to Multipurpose (0).
Just select the groups, create an agent with this code, that runs on selected documents:
FIELD GroupType := "0";
If you really want to do the selection in your agent, then let it run on "all documents in view" and add a selection before the action:
SELECT #Begins( ListName ; "GD" );
FIELD GroupType := "0";
As this will run a lot slower I would manually select the groups and use the first agent as selecting is as easy as setting the cursor to the first group with "GD", then scroll down to the last one and click it while holding the Shift- Key.

Login validation with database

PROBLEM
Hello! I need to make login in Delphi 2010. I have MS Access database where I have fields (loginID, username, password). So I have 2 TEdit components for username and password. I have connected to database in delphi and all connections are working.
So problem is that I don't know how to check if text from TEdit is in database. I need something like query.
Example:
if Edit1.Text in login.username then
something
else
something else
Hope you understand what I need, but anyway you can ask a questions for more information. I will be thankful for solution.
WHAT I TRYED
ADOQuery1.SQL.Text := 'SELECT FROM login WHERE username = :Edit1.Text';
ADOQuery1.ExecSQL;
I don't know if it works.
How to check like this:
if ADOQuery1 execute then
something
else
something else
You need to properly parameterize your query, and use the Parameters. (You also need to write valid SQL, which for a SELECT requires a list of columns you want returned.)
ADOQuery1.SQL.Text := 'SELECT UserName FROM login WHERE username = :User';
ADOQuery1.Parameters.ParamByName('User').Value := Edit1.Text;
You then need to open (not execute) the query, and see if it returned a value.
ADOQuery1.Open;
if not ADOQuery1.IsEmpty then
begin
// User exists. Do whatever you need next.
end
else
// Do what you want if user not found
I'd strongly suggest that if you're going to try and use databases, you buy a book or find a tutorial. SELECT is one of the most basic operations you'll need to perform.

Delphi Parameterised Query won't work

I'm only a beginner in learning to use Parameterised Queries as I used to do a lot of concatentating before. I've been trying to get this query below to work. It is a simple 'Book' table, with a field called 'BookTitle'. I have a simple textbox where I invite the user to enter any title...and it should run the query below to find if that book exists. Below is my code that, when run, manages to compile. However, when an entry into the textbox is added and the button to run the query is pressed, a Debugger Exception Notification appears with the following statement.
Debugger Exception Notification: Project Project1.exe raised exception class EOleException with message 'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another'.
I then have the option to press 'Break' or 'Continue'. If I press 'Break', the line:
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
is filled with a purple/red colour (not sure what this means?).
That said, if I press 'Continue', the program will work as expected, and will continue to do so. Here is the code i've been testing.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var BookEntry:string;
begin
BookEntry:=edtBookTitle.Text;
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
Further points to note: The components in my Delphi form are as follows
a TADOQuery named 'qbook',
a TDataSource,
a TDBGrid,
aTEdit into which the user enters their desired search criteria and
a TButton that once pressed, initiates the query.
With regards to the database, it is:
a MySQL database (Community Edition)
a table named 'Book', where BookID is the PK and is of INT data type.
a field entitled 'BookTitle' which i've set as VARCHAR(35). It is not part of the key. However, it is in the BookTitle field, that i want to apply my query.
NOTE: This answer was posted based on the original code in the question, which has been edited to match what is in my answer. See the question's revision history for the first version of the question on which my answer was based.
The solution you saw in the other post was correct; it was just for a standard TQuery and not TADOQuery. TADOQuery requires a couple of minor syntax changes:
Use Parameters.ParamByName() instead of Parameters
Set a DataType for each parameter before using it
Use .Value instead of .AsString
Here's a corrected version of your code (which also includes setting a value for BookTitle before using it.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var
BookEntry:string;
begin
BookEntry := 'Some book title'; // or QueryEdit.Text or whatever
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
I have never known a string type query parameter need the datatype or whatever set, I would simply remove any reference to the datatype.
After all, if it hurts when you bang your head on a wall, just stop banging it.

Delphi+SQL form is blinking while scrolling

I have 2 tables related by ID on MS SQL. Delphi-interface looks like 2 DBGrids. By selecting one record from the top table, the bottom table shows all the records with this ID. DBGrid is connected to a stored procedure (TMSStoredProc) that simply displays all records with a given ID. Top table AfterScroll event:
Bottom_table_SP.ParamByName('#ID').AsInteger := Top_table_SP.FieldByName('ID').AsInteger;
Bottom_table_SP.Active := False;
Bottom_table_SP.Active := True;
Everything's very simple, and it works. But while I scroll fast top table, the whole form starts to blink - size of top-table and bottom-table changes in the millisecond. Does anyone know how to handle this kind of problem?
Since you mention SQL Server, I'm guessing you're using the ADO components (TADOStoredProcedure) here, so the normal MasterFields and MasterSource properties aren't available. You still have the basic functionality for other things, so you should use TDataSet.DisableControls and EnableControls to avoid this flickering:
Bottom_table_SP.DisableControls;
try
Bottom_table_SP.Active := False;
Bottom_table_SP.ParamByName('#ID').AsInteger := Top_table_SP.FieldByName('ID').AsInteger;
Bottom_table_SP.Active := True;
finally
Bottom_table_SP.EnableControls;
end;
You might find Disabling and Enabling Data Display useful to explain.

MOSS 2007: What is the source of "Directories"?

I'm trying to generate a new SharePoint list item directly using SQL server. What's stopping me is damn tp_DirName column. I have no ideas how to create this value.
Just for instance, I have selected all tasks from AllUserData, and there are possible values for the column: 'MySite/Lists/Task', 'Lists/Task' and even 'MySite/Lists/List2'.
MySite is the FullUrl value from Webs table. I can obtain it. But what about 'Lists/Task' and '/Lists/List2'? Where they are stored?
If try to avoid SQL context, I can formulate it the following way: what is the object, that has such attribute as '/Lists/List2'? Where can I set it up in GUI?
Just a FYI. It is VERY not supported to try and write directly to SharePoint's SQL Tables. You should really try and write something that utilizes the SharePoint Object Model. Writing to the SharePoint database directly mean Microsoft will not support the environment.
I've discovered, that [AllDocs] table, in contrast to its title, contains information about "directories", that can be used to generate tp_DirName. At least, I've found "List2" and "Task" entries in [AllDocs].[tp_Leaf] column.
So the solution looks like this -- concatenate the following 2 components to get tp_DirName:
[Webs].[FullUrl] for the web, containing list, containing item.
[AllDocs].[tp_Leaf] for the list, containing item.
Concatenate the following 2 components to get tp_Leaf for an item:
(Item count in the list) + 1
'_.000'
Regards,
Well, my previous answer was not very useful, though it had a key to the magic. Now I have a really useful one.
Whatever they said, M$ is very liberal to the MOSS DB hackers. At least they provide the following documents:
http://msdn.microsoft.com/en-us/library/dd304112(PROT.13).aspx
http://msdn.microsoft.com/en-us/library/dd358577(v=PROT.13).aspx
Read? Then, you know that all folders are listed in the [AllDocs] table with '1' in the 'Type' column.
Now, let's look at 'tp_RootFolder' column in AllLists. It looks like a folder id, doesn't it? So, just SELECT the single row from the [AllDocs], where Id = tp_RootFolder and Type = 1. Then, concatenate DirName + LeafName, and you will know, what the 'tp_DirName' value for a newly generated item in the list should be. That looks like a solid rock solution.
Now about tp_LeafName for the new items. Before, I wrote that the answer is (Item count in the list) + 1 + '_.000', that corresponds to the following query:
DECLARE #itemscount int;
SELECT #itemscount = COUNT(*) FROM [dbo].[AllUserData] WHERE [tp_ListId] = '...my list id...';
INSERT INTO [AllUserData] (tp_LeafName, ...) VALUES(CAST(#itemscount + 1 AS NVARCHAR(255)) + '_.000', ...)
Thus, I have to say I'm not sure that it works always. For items - yes, but for docs... I'll inquire into the question. Leave a comment if you want to read a report.
Hehe, there is a stored procedure named proc_AddListItem. I was almost right. MS people do the same, but instead of (count + 1) they use just... tp_ID :)
Anyway, now I know THE SINGLE RIGHT answer: I have to call proc_AddListItem.
UPDATE: Don't forget to present the data from the [AllUserData] table as a new item in [AllDocs] (just insert id and leafname, see how SP does it itself).