SQL Delphi "Parameter 'Subject' not found" - sql

I have recently started to learn how to code in Delphi since moving from Python to do a project. I can't seem to find a fix to this issue. I have searched online for a couple of hours now and none of the 'fixes' seem to be working. I have tried using 'Query.ExecSQL', I have tried breaking the code up into segments, I have tried to assign edtSubject.Text to a variable and doing it that way, among a handful of other 'solutions' that haven't fixed the issue. I am really struggling with this and need a way to fix it that works quick, here is my code:
Query := TADOQuery.Create(Self);
Query.Connection := ADOConnection;
Query.SQL.Add('INSERT INTO tbl_RFI (Subject) VALUES (:Subject)');
Query.Parameters.ParamByName('Subject').Value := edtSubject.Text;
Query.ExecSQL;
I really hope that someone can help me with this,
Thanks.

Just add Query.ParamCheck := true before setting the SQl Text and it should be fine

Despite what others say I have had this same thing happen from time to time over the years in my production code.
Parameter 'ParameterName' not found
Always with ADO objects that were created in code. The best fix that I have found was here http://edn.embarcadero.com/article/20420
Basically just force the ADO object to reparse the parameters before you reference them.
EDIT: Thanks to Ken's feedback I have added a test first to check if the parameter exists before calling ParseSQL, thereby conserving the execution plan for the 99.9% of the time.
with TADODataSet.Create(nil) do
try
Connection := MyADOConnection;
CommandText := 'SELECT Foo ' +
'FROM FooBar ' +
'WHERE Bar = :Bar ';
if Parameters.FindParam('Bar') = nil then
Parameters.ParseSQL(CommandText, True); {<- THIS IS THE FIX }
Parameters.ParamByName('Bar').Value := 'value';
Open;
finally
Free;
end;
Since adding the ParseSQL I haven't had the problem.

Late reply I know, but I just went through the same situation, so in case this helps someone else. And it happens at random, "parameter not found" during in my case a tadocommand. Program errors out, restart doing exactly same sequence of events and works fine. Load up compiler, step through and works just fine. Set a breakpoint, and I can see the parameter not defined. But again, it's not every time, it's kind of random.
So it feels like some type of timing issue. I tried the ParseSQL command, and that actually makes it error out every time with a different error. I think the command text was getting cropped but did not investigate this. (it's a fairly long command)
Anyway, it seems I was able to fix this by adding in an application.processmessages after my tadocommand is created and sql text assigned.

Related

Object name contains more than the maximum prefixes allowed

I have seen a lot of questions about this but I couldn't find the correct answer for me which works.
The object which triggers the problem is like
test123.de.company.com.Database.dbo.Table
Test123.de.company.com
is the database Server.
Object name contains more than the maximum prefixes allowed
I have tried to write it like this [test123.de.company.com].Database.dbo.Table just like [test123.de.company.com].[Database].[dbo].[Table]
Can you tell me what's wrong with this?
Please try this:
["test123.de.company.com"].[Database].[dbo].[Table]
OP also encountered a new problem after implementing this solution above. OP said:
Thank you! This worked for me. To be more precise, the join is for a
view and if I save/close and then later get back to the design option
the quote marks are removed and there is [test123.de.company.com] left
over and the error returns. Is there a way to keep them fixed?
Otherwise if I change anything I always have to add the quote marks
again and again
Then with the help of DaleK that problem also was solved. DaleK:
Don't use the design option, script it as alter instead

TADOQuery - Edit mode inserts new record rather than editing

I'm puzzled at the behavior of the TADOQuery, let's just call Q. When I use Q.Edit, populate some fields, then Post, it ends up actually inserting a new record.
The code is simple, and reading the ID from an object:
Q.SQL.Text := 'select * from SomeTable where ID = :id';
Q.Parameters.ParamValues['id'] := MyObject.ID;
Q.Open;
try
Q.Edit;
try
Q['SomeField']:= MyObject.SomeField;
finally
Q.Post;
end;
finally
Q.Close;
end;
To my surprise, rather than updating the intended record, it decided to insert a new record. Stepping through the code, immediately after Q.Edit, the query is actually in Insert mode.
What could I be doing wrong here?
I think the comments that this behaviour is documented are off the point. What the docs don't make clear (possibly because the point never occurred to the author) is that this behaviour is not guaranteed to be deterministic.
The innards of TDataSet.Edit have scarcely changed in decades. Here is the Seattle version:
procedure TDataSet.Edit;
begin
if not (State in [dsEdit, dsInsert]) then
if FRecordCount = 0 then Insert else
begin
CheckBrowseMode;
CheckCanModify;
DoBeforeEdit;
CheckParentState;
CheckOperation(InternalEdit, FOnEditError);
GetCalcFields(ActiveBuffer);
SetState(dsEdit);
DataEvent(deRecordChange, 0);
DoAfterEdit;
end;
end;
Now, notice that the if .. then .. is predicated on the value of FRecordCount, which at various points in the TDataSet code is forced to have a given assumed value (variously 1, 0 or something else) by code such as in SetBufferCount and that behaviour isn't documented at all. So on reflection I think Jerry was probably right to expect that attempting to edit a non-existent record should be treated as an error condition, and not be fudged around by silently calling Insert whether or not it is documented.
I'm posting both a question and an answer, because the cause of the problem was totally unexpected behavior, and surely someone else had the same bewildering thing happen.
This happens in the event that the dataset you're trying to edit doesn't have any records. Personally, I would think it should produce an exception that you can't edit when there's no records. But the TADOQuery decides to append a new record instead.
The very root cause of this issue was that the object where I supplied the ID actually had a value of 0, and therefore since there's no record in the database with ID 0, it returned nothing.

How to execute SQL Script which may or may not return data?

This is an extension of an old question of mine where the answer wasn't quite what I was asking. What I'm doing is executing SQL Script on an MS SQL Server database. This script may or may not return any recordsets. The problem is that the way that ADO components work, at least to my knowledge, I can only explicitly request one or the other.
If I know a query will return data, I use TADOQuery.Open
If I know a query will not return data, I use TADOConnection.Execute
If I don't know whether query will return data or not... ???
How can I execute any query and read the response to determine whether it has any recordsets or not so I can read that recordset?
What I've tried:
Calling TADOQuery.Open, but raises exception if there's no recordset
Calling TADOQuery.ExecSql, but never returns any data
Calling TADOConnection.Execute, but never returns any data
Using Option 3 and reverting to Option 1 on exceptions, but this is double the work (script files over 38,000 lines) and kinda nasty.
Using TADOCommand.Execute, but keeps raising "Parameter object is improperly defined. Inconsistent or incomplete information was provided" on creating some stored procedures (which otherwise don't happen when using TADOConnection.Execute).
Calling TADOConnection.Execute overload which returns _Recordset, but then the TADOConnection.Errors returns empty (and I depend on this).
Just as some background, the purpose is to implement something like the SQL Query tool in the SQL Server Management Studio. It allows you to execute any SQL script, and if it returns any recordsets, it displays them, otherwise it just displays output messages. The tool I'm working on automatically breaks SQL Script at GO statements, and executes each individual block separately. Some of those blocks might return data, and others might not. It's already obvious that I cannot make this determination prior to execution, so I'm looking for a way to go ahead with the execution and observe the result. TADOConnection.Execute provides some useful information, including the Errors (or output messages).
As of now, the only option I have is to supply an option in the user interface to allow the user to choose which type of execution to use - but this is what I'm trying to eliminate.
EDIT
The TADOCommand.Execute method is the closest to what I want. However, it fails on some bits of script which otherwise work perfectly fine using TADOConnection.Execute. See #5 above in "What I've tried". I almost wrote that as my answer, until I found this error happens on almost everything.
EDIT
After posting my answer below, I then came to learn that the Errors property no longer returns anything when I use this other overload of Execute. See #6 above in "What I've tried".
Calling...
ADOConnection1.Execute('select * from something', cmdText, []);
...does not return anything in ADOConnection1.Errors, whereas...
var
R: Integer;
begin
ADOConnection1.Execute('select * from something', R);
...does return messages in ADOConnection1.Errors, which is what I need, but yet, doesn't return any recordsets.
EDIT: Not the right solution
I discovered my solution finally after digging even deeper. The answer is to use the TADOConnection.Execute() overload which supports returning the recordset:
function TADOConnection.Execute(const CommandText: WideString;
const CommandType: TCommandType = cmdText;
const ExecuteOptions: TExecuteOptions = []): _Recordset;
Then, just assign the resulting _Recordset to the Recordset property of supported dataset components.
var
RS: _Recordset;
begin
RS := ADOConnection1.Execute('select * from something', cmdText, []);
if Assigned(RS) then begin
ADODataset1.Recordset:= RS;
...
end;
end;
The downside is that you cannot use the other overload which supports returning the RowsAffected. Also, nothing is returned in the Errors property of the TADOConnection when using this overload version of Execute, whereas the other one does. But that other doesn't return a recordset.

local variable referenced before assignment frequently occurring error

Hello I've done multiple python programs since I started and an error is occurring quite often for a short time and I don't understand why there is an error or why by just changing random things so the program does the same gets rid of it so can anybody please explain how the "referenced before assignment" error occurs please.
Here's the code with the problem:
def compter(sequence, element):
comtpe=0
for i in sequence:
if element==sequence[i]:
compte+=1
return compte
compter([1,2,1,1], 1)
please explain so I could be able to get rid of it in any future code thank you very much :)
(I'musing python 2.7.6)

The specified RegistryOptions value is invalid

What im trying to do is write a key to the registry but im stepping from one problem to another, first permissions problem, now this..
This is the line of code.
If PNGchk.Checked = True Then
My.Computer.Registry.Users.CreateSubKey(UserSID & "\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\UserChoice", True, Security.AccessControl.RegistryRights.FullControl).SetValue("Progid", "SIV.png", Microsoft.Win32.RegistryValueKind.String)
End If
You must have Option Strict Off for that code to even compile, so you might want to fix that to start with. Option Strict On would have flagged issues with that code right away. You should read the documentation or at least pay attention to Intellisense for that method because your second and third arguments make no sense. No overload that I can see has a Boolean parameter and if you want to use a RegistryRights value you do so within a RegistrySecurity object as far as I can see.
RegistryKeyPermissionCheck.ReadWriteSubTree worked for me.
Using clsid64 = view64.CreateSubKey("Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\UserChoice", RegistryKeyPermissionCheck.ReadWriteSubTree)
clsid64.SetValue("StubPath", "SIV.png")
clsid64.Close()
End Using