Help me to fix this problem to delete records with TFDQuery.
When this value of record is choosed by me with Edit.Text or DBEdit.Text, I try like this but it is not working:
FDQuery.SQL.Text := 'delete * FROM MyTable column_name =:KEY1 ';
FDQuery.ParamByName('KEY1').AsString = 'dbedit.text';
FDQuery.Open;
fdquery.SQL.Text := 'DELETE FROM MyTable WHERE column_name = :KEY1';
fdquery.ParamByName('KEY1').AsString := dbedit.Text;
fdquery.Execute();
You could also use TFDCommand rather than TFDQuery as you are not expecting to read the result:
fdcommand.CommandText := 'DELETE FROM MyTable WHERE column_name = :KEY1';
fdcommand.ParamByName('KEY1').AsString := dbedit.Text;
fdcommand.Execute();
If this is a command you expect to re-use you could put the SQL statement into the command at design time, with the parameter name, and then at run time you would only need to do:
fdcommand.ParamByName('KEY1').AsString := dbedit.Text;
fdcommand.Execute();
Depending on the underlying database you are using have commands pre-populated can allow the query to be prepared in advance. For complex queries (unlike this one) this means that the execution plan is built only once.
Related
i'm learning to use firemonkey, and i made an app that i'm using on my phone (it works like a reminder if u want) so basically there's a database file (SQLite) in my phone's internal storage, and in the form i put a TMemo + FDConnection + FDPhysSQLiteDriverLink so the app can read the database and display it on the TMemo, now i did put a TEdit and i added a button i want what i write on the TEdit to be added to the database.
i'm new to SQL delphi and stack overflow in general.
thanks
PS: i'm trying to do it without using livebindings.
var
query: TFDQuery;
begin
query := TFDQuery.Create(nil);
try
// Define the SQL Query
query.Connection := FDConnection1;
query.SQL.Text := 'SELECT * FROM Employee';
query.Open();
outputMemo.Text := '';
// Add the field names from the table.
outputMemo.Lines.Add(String.Format('|%8s|%-25s|%-25s|', [' ID ', ' NAME >',
' DEPARTMENT ']));
// Add one line to the memo for each record in the table.
while not query.Eof do
begin
outputMemo.Lines.Add(String.Format('|%8d|%-25s|%-25s|',
[query.FieldByName('ID').AsInteger, >query.FieldByName('Name').AsString,
query.FieldByName('Department').AsString]));
query.Next;
end;
finally
query.Close;
query.DisposeOf;
end;
end;
this is the code to display the database, i want to know if there's a way to write on the memo or a TEdit and press a button to change back the database, i'm wondering if it works both ways.
Sometimes during Dynamics NAV development, it is helpful to take a quick look at the data using SQL Server. But because any fields of type option are an enumeration, all you get in SQL Server is the numeric value. I needed a quick and dirty way to get the option text values instead.
From within NAV you can read the OPTIONSTRING property of a FieldReference. This is a comma separated string. A job can be scheduled that will loop through all of the tables (Object virtual table filtered on table) by number, find the options strings and add them to a table. Then in a query you can find the option text value for the Table, Field No, and Field Value.
RecRef.OPEN(TableNo);
FOR i := 1 TO RecRef.FIELDCOUNT DO BEGIN
FieldRef := RecRef.FIELDINDEX(i);
IF FORMAT(FieldRef.TYPE) = 'Option' THEN BEGIN
optionstring := FieldRef.OPTIONSTRING;
c := NumberofOptions(optionstring);
FOR o := 1 TO c DO BEGIN
OptionsTable.INIT;
OptionsTable."Table No" := TableNo;
OptionsTable."Field No" := FieldRef.NUMBER;
OptionsTable."Option Value" := o-1;
OptionsTable."Option Text" := SELECTSTR(o, optionstring);
OptionsTable."Field Name" := FieldRef.NAME;
IF NOT OptionsTable.INSERT THEN OptionsTable.DELETE;
END;
END;
END;
To make this a little less painful, I created a macro enabled Excel file that parses the Dynamics NAV field option string into a Sql Server T-Sql Case statement. It provides a horizontal or vertical case statement and uses the field name as the column alias in Sql Server. Enjoy...
Here is a link to the Excel file
Excel File
I often get this problem. I created a table with option values (int) and names (string). The primary key is code, value. So you can use it also to resolve magicnumbers from other systems. Then you can easy join this table:
select Type, i.[Option] [Option Name]
from Object o
join [xxx$IntegerToOption] i on i.Code = 'OBJEKT TYP' and i.Integer = o.Type
order by o.Name
Output:
Type Option Name
5 Codeunit
2 Form
1 Table
2 Form
2 Form
1 Table
2 Form
5 Codeunit
3 Report
I have a view in my database that has a bunch of fields derived from other information in the database, this is how the view is defined:
create view patient_account_view AS
select patient.p_mrn,
p_fname,
p_lname,
ammount_paid,
quantity*item_cost + repeats*item_cost "ammount_owing",
(quantity*item_cost + repeats*item_cost) - ammount_paid "balance"
from patient_account,
patient,
diagnosis,
prescribed_treatment,
items_used,
item,
perscription
where patient.p_mrn = diagnosis.p_mrn AND
patient_account.p_mrn = patient.p_mrn AND
diagnosis.prescribed_treatment_id = prescribed_treatment.prescribed_treatment_id AND
prescribed_treatment.prescribed_treatment_id = perscription.prescribed_treatment_id AND
items_used.ptreatment_id = prescribed_treatment.prescribed_treatment_id AND
items_used.item_number = item.item_number;
I would like to use pl/sql to access the information in the view to stick it into a form, but I'm getting a 'bad bind variable' error. How do I access this kind of attribute without having to recalculate the information stored there?
Here is the plsql that is problematic:
DECLARE
pmrn patient.p_mrn%TYPE;
var_ptuple patient%ROWTYPE;
var_accttuple patient_account%ROWTYPE;
BEGIN
pmrn := :PATIENT_BLOCK.MRN_FIELD;
SELECT * INTO var_ptuple from patient WHERE patient.p_mrn = pmrn;
SELECT * INTO var_accttuple from patient_account_view WHERE patient_account_view.p_mrn = pmrn;
:PATIENT_BLOCK.FNAME := var_ptuple.p_fname;
:PATIENT_BLOCK.LNAME := var_ptuple.p_lname;
:PATIENT_BLOCK.BALACNCE_OWING := var_accttuple.balance;
END;
The columns of your view patient_account_view do not match exactly the columns of the table patient_account, but in your code you have:
var_accttuple patient_account%ROWTYPE;
which means when you run this:
SELECT * INTO var_accttuple from patient_account_view ...
You haven't specified which columns get mapped to which record attributes, so Oracle requires that the column list matches exactly.
In this case, I'd expect you probably want to change the definition of the variable, e.g.
var_accttuple patient_account_view%ROWTYPE;
Side note
Since you're only using one attribute from the view, you can simplify your code as follows:
SELECT balance INTO :PATIENT_BLOCK.BALACNCE_OWING
from patient_account_view WHERE patient_account_view.p_mrn = pmrn;
and you no longer need var_accttuple.
My Delphi application is connected to SQLite successfully.
procedure TForm1.Button1Click(Sender: TObject);
begin
ZQuery1.Close;
ZQuery1.SQL.Clear;
ZQuery1.SQL.Text := 'SELECT Name FROM city;';
ZQuery1.Open;
while not ZQuery1.EOF do
begin
Memo1.Lines.Add(ZQuery1.FieldValues['name']);
ZQuery1.Next;
end;
end;
The above code works fine and loads contents of field name from table city.
However,
procedure TForm1.Button1Click(Sender: TObject);
begin
ZQuery1.Close;
ZQuery1.SQL.Clear;
ZQuery1.SQL.Text := 'Select name from city WHERE district = :aField';
ZQuery1.Params.ParamByName('aField').Value := 'kabol';
ZQuery1.Open;
while not ZQuery1.EOF do
begin
Memo1.Lines.Add(ZQuery1.FieldValues['name']);
ZQuery1.Next;
end;
end;
Surprisingly, when I add a where clause, the query returns nothing! Could anyone suggest what is wrong in my code?
Here is an image of the data in my table:
You probably don't have any data that has a district of kabol. The addition of the WHERE clause would then result in no rows being returned, meaning that ZQuery1.Eof is immediately true, and your while not ZQuery1.Eof do loop never gets entered.
You can check this by changing your first query (the one that works) to something like this:
ZQuery1.SQL.Text := 'SELECT Name, District FROM City';
Then change the output to
Memo1.Lines.Add(ZQuery1.FieldValues['name'] + #9 +
ZQuery1.FieldValues['district']);
If you don't see at least one line in the memo that contains kabol in the rightmost column, you don't have any rows that match your WHERE criteria. (Note that most databases are case-sensitive, so kabol is not equal to Kabol; the first would match your WHERE, but the second would not.)
Your screenshot shows one database row where district is 'Kabol' (uppercase K), but your SQL query is looking for 'kabol' (lowercase k) instead. Assuming the query is comparing strins case-sensitively, that would explain why no row is found. So either fix the case in your query input, or else perform a case-insensitive query instead.
I'm trying to insert a record into a table in a 3-tier database setup, and the middle-tier server generates the error message above as an OLE exception when it tries to add the first parameter to the query.
I've Googled this error, and I find the same result consistently: it comes from having a colon in a string somewhere in your query, which b0rks ADO's SQL parser. This is not the case here. There are no spurious colons anywhere. I've checked and rechecked the object definition against the schema for the table I'm trying to insert into. Everything checks out, and this has my coworkers stumped. Does anyone know what else could be causing this? I'm at my wits' end here.
I'm using Delphi 2007 and SQL Server 2005.
I can get this error, using Delphi 2007 and MSSQL Server 2008, and I found a workaround. (which is pretty crappy IMHO, but maybe its useful to you if yours is caused by the same thing.)
code to produce the error:
with TADOQuery.Create(nil)
do try
Connection := ADOConnection;
SQL.Text := ' (SELECT * FROM Stock WHERE InvCode = :InvCode ) '
+' (SELECT * FROM Stock WHERE InvCode = :InvCode ) ';
Prepared := true;
Parameters.ParamByName('InvCode').Value := 1;
Open; // <<<<< I get the "parameter object is...etc. error here.
finally
Free;
end;
I found two ways to fix it:
1) remove the brackets from the SQL, ie:
SQL.Text := ' SELECT * FROM Stock WHERE InvCode = :InvCode '
+' SELECT * FROM Stock WHERE InvCode = :InvCode ';
2) use two parameters instead of one:
with TADOQuery.Create(nil)
do try
Connection := ADOConnection;
SQL.Text := ' (SELECT * FROM Stock WHERE InvCode = :InvCode1 ) '
+' (SELECT * FROM Stock WHERE InvCode = :InvCode2 ) ';
Prepared := true;
Parameters.ParamByName('InvCode1').Value := 1;
Parameters.ParamByName('InvCode2').Value := 1;
Open; // <<<<< no error now.
finally
Free;
end;
I found this thread while searching the previously mentioned Exception message. In my case, the cause was an attempt to embed a SQL comment /* foo */ into my query.sql.text.
(I thought it would have been handy to see a comment go floating past in my profiler window.)
Anyhow - Delphi7 hated that one.
Here a late reply. In my case it was something completely different.
I tried to add a stored procedure to the database.
Query.SQL.Text :=
'create procedure [dbo].[test]' + #13#10 +
'#param int ' + #13#10 +
'as' + #13#10 +
'-- For the parameter you can pick two values:' + #13#10 +
'-- 1: Value one' + #13#10 +
'-- 2: Value two';
When I removed the colon (:) it worked. As it saw the colon as a parameter.
I just encountered this error myself. I'm using Delphi 7 to write to a 2003 MS Access database using a TAdoQuery component. (old code) My query worked fine directly in MS Access, but fails in Delphi through the TAdoQuery object. My error came from a colon (apologies to the original poster) from a date/time value.
As I understand it, Jet SQL date/time format is #mm/dd/yyyy hh:nn:ss# (0 left-padding is not required).
If the TAdoQuery.ParamCheck property is True then this format fails. (Thank you posters!) Two work-arounds are: a) set ParamCheck to False, or b) use a different date/time format, namely "mm/dd/yyyy hh:nn:ss" (WITH the double quotes).
I tested both of these options and they both worked.
Even though that double-quoted date/time format isn't the Jet date/time format, Access is pretty good at being flexible on these date/time formats. I also suspect it has something to do with the BDE/LocalSQL/Paradox (Delphi 7's native SQL and database engine) date/time format (uses double quotes, as above). The parser is probably designed to ignore quoted strings (double quotes are the string value delimiter in BDE LocalSQL), but may stumble somewhat on other non-native date/time formats.
SQL Server uses single quotes to delimit strings, so that might work instead of double quotes when writing to SQL Server tables (not tested). Or maybe the Delphi TAdoQuery object will still stumble. Turning off ParamCheck in that case may be the only option. If you plan to toggle the ParamCheck property value in code, you'll save some processing time by ensuring the SQL property is empty before enabling it, if you're not planning on parsing the current SQL.
I'm facing the same error described in your question. I've traced the error into ADODB.pas -> procedure TParameters.AppendParameters; ParameterCollection.Append(Items[I].ParameterObject).
By using breakpoints, the error was raised, in my case, by a parameter which should fill a DateTime field in the database and I've never filled up the parameter. Setting up the parameter().value:='' resolved the issue (I've tried also with varNull, but there is a problem - instead of sending Null in the database, query is sending 1 - the integer value of varNull).
PS: I know is a 'late late late' answer, but maybe somebody will reach at the same error.
If I remember well, you have to explicit put NULL value to the parameter. If you are using a TAdoStoredProc component, you should do this in design time.
Are you using any threading? I seem to remember getting this error when a timer event started a query while the ADO connection was being used for another synchronous query. (The timer was checking a "system available" flag every minute).
Have you set the DataType of the parameter or did you leave it as ftUnknown?
I have also had the same problem, but with a dynamic command (e.g. an Update statement).
Some of the parameters could be NULL.
The only way i could get it working, was setting the parameter.DataType := ftString and parameter.Size := 1 and not setting the value.
cmdUpdate := TADOCommand.Create(Self);
try
cmdUpdate.Connection := '**Conections String**';
cmdUpdate.CommandText := 'UPDATE xx SET yy = :Param1 WHERE zz = :Param2';
cmdUpdate.Parameters.ParamByName('Param2').Value := WhereClause;
if VarIsNull(SetValue) then
begin
cmdUpdate.Parameters.ParamByName('Param1').DataType := ftString;
cmdUpdate.Parameters.ParamByName('Param1').Size := 1;
end else cmdUpdate.Parameters.ParamByName('Param1').Value := SetValue;
cmdUpdate.Execute;
finally
cmdUpdate.Free;
end;
I just ran into this error today on a TADOQuery which has ParamCheck := False and has no colons in the SQL.
Somehow passing the OLECMDEXECOPT_DODEFAULT parameter to TWebBrowser.ExecWB() was causing this for me:
This shows the problem:
pvaIn := EmptyParam;
pvaOut := EmptyParam;
TWebBrowser1.ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT, pvaIn, pvaOut);
This does not show the problem:
pvaIn := EmptyParam;
pvaOut := EmptyParam;
TWebBrowser1.ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DONTPROMPTUSER, pvaIn, pvaOut);
A single double quote in the query can also raise this error from what I just experienced and I am not using parameters at all ...
You can get this error when attempting to use a time value in the SQL and forget to wrap it with QuotedStr().
I got the same error. Turned out, that it is because a parameter of the stored procedure was declared as varchar(max). Made it varchar(4000) and error disappeared.