我正在尝试使用datasnap(之前从未使用过它)并遇到了一个奇怪的问题。 也许我做错了,我不知道。 我在表单上放了一个Clientdataset3。将它链接到SQLConnection1(在同一表格上) 哪个连接到datasnap服务器。 我还将Clientdataset3链接到服务器端的datasetprovider(允许命令文本) 链接到我要插入的表。但是当我跑步时:
procedure TForm3.AdvGlowButton1Click(Sender: TObject);
begin
clientdataset3.CommandText:='insert into "MY_TABLE" (twit) values (:A)';
clientdataset3.Params.ParamByName('A').AsString := cxmemo1.Lines.Text;
clientdataset3.Execute;
end;
我得到"远程错误:没有这样的表:插入"
我做错了什么?数据库是通过DBX的SQLite,使用XE6。
答案 0 :(得分:1)
如果您使用SELECT语句填充CDS,则无需执行发送定制INSERT语句的练习。
您应该可以致电
ClientDataSet3.Insert;
// populate fields here
ClientDataSet3.Post;
然后调用ClientDataSet3.ApplyUpdates。
同样,您只需调用ClientDataSet3.Delete即可执行DELETE。
必要的INSERT,DELETE和UPDATE语句的构造由CDS的提供者处理。但是,我并不打算建议您无法按照您尝试的方式执行INSERT - 它应该可以正常工作。
我无法从这里告诉你INSERT出了什么问题,所以相反,这里有一些适合我的代码(包括CREATE TABLE,etc语句),所以你可以& #34;发现差异。"我在2014年6月4日的Win7 64位和sqlite3.dll v.3.8.5.0上使用了XE6。
示例代码提供了执行插入的3种方式(全部检查和工作),两种使用自定义INSERT语句,第三种使用CDS的默认插入行为,可以在代码(CDS1.Insert)中调用点击' +' DBNavigator上的按钮。默认的CDS插入行为需要特殊处理:尽管服务器上的ID列定义为Autoinc,但在执行CDS插入时获取autoinc值是有问题的,因此代码使用此处描述的方法:
http://edn.embarcadero.com/article/20847
生成临时的否定ID值,该值在CDS ApplyUpdates过程中被替换。请注意,DFM中有关SqlQuery ID字段中有关ProviderFlags的链接的勘误部分中引用的度量是必需的,因为服务器上的ID列值是64位整数。
type
TDataOperation = (doCreateTable, doDropTable, doInsert, doInsertUsingParams, doSelect);
TForm3 = class(TForm)
[...]
{ private declarations }
ID : Int64;
function NextID : Int64;
[...]
end;
implementation
{$R *.dfm}
const
scCreateTable = 'CREATE TABLE [MATable2] ([ID] INTEGER NOT NULL '
+ #13#10 + 'PRIMARY KEY AUTOINCREMENT, [AName] VARCHAR(20), '
+ #13#10 + ' [AMemo] MEMO)';
scDropTable =
'DROP TABLE [MATable2]';
scInsert1 =
'INSERT INTO [MATable2] (AName, AMemo) VALUES(''a'', ''A memo'')';
scSelect =
'SELECT * FROM [MATable2]';
scInsertUsingParams =
'INSERT INTO [MATable2] (AName, AMemo) VALUES(:AName, :AMemo)';
procedure TForm3.PerformTableOperation(Operation : TDataOperation);
var
Param : TParam;
begin
if {(Operation in [toCreate, toDrop]) and} CDS1.Active then
CDS1.Close;
case Operation of
doCreateTable : begin
CDS1.CommandText := scCreateTable;
CDS1.Execute;
PerformTableOperation(doSelect);
end;
doDropTable : begin
CDS1.CommandText := scDropTable;
CDS1.Execute;
end;
doSelect : begin
CDS1.CommandText := scSelect;
CDS1.Open;
end;
doInsert : begin
CDS1.CommandText := scInsert1;
CDS1.Execute;
PerformTableOperation(doSelect);
end;
doInsertUsingParams : begin
CDS1.CommandText := scInsertUsingParams;
// CDS1.FetchParams;
CDS1.Params.ParamByName('AName').AsString:= 'bcdef';
CDS1.Params.ParamByName('AMemo').AsString := 'memo b';
CDS1.Execute;
CDS1.Params.Clear;
PerformTableOperation(doSelect);
end;
end;
if CDS1.Active then // it won't be after a toDrop
CDS1.ApplyUpdates(-1);
end;
procedure TForm3.OpenConnection;
begin
SqlConnection1.Open;
end;
procedure TForm3.btnCreateClick(Sender: TObject);
begin
PerformTableOperation(doCreateTable);
end;
[etc ...]
procedure TForm3.btnReopenClick(Sender: TObject);
begin
CDS1.Close;
PerformTableOperation(doSelect);
end;
procedure TForm3.btnSelectClick(Sender: TObject);
begin
PerformTableOperation(doSelect);
end;
procedure TForm3.CDS1AfterDelete(DataSet: TDataSet);
begin
CDS1.ApplyUpdates(-1);
end;
procedure TForm3.CDS1AfterPost(DataSet: TDataSet);
begin
CDS1.ApplyUpdates(-1);
end;
procedure TForm3.CDS1NewRecord(DataSet: TDataSet);
begin
CDS1.FieldByName('ID').AsInteger := NextID;
end;
function TForm3.NextID: Int64;
begin
Dec(ID);
Result := ID;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
OpenConnection;
end;
end.
这是一个部分DFM,可以最大限度地减少猜测我的数据库组件设置方式的必要性。
object Form3: TForm3
[...]
object DBGrid1: TDBGrid
Left = 8
Top = 8
Width = 456
Height = 193
DataSource = DataSource1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'Tahoma'
TitleFont.Style = []
Columns = <
item
Expanded = False
FieldName = 'ID'
Visible = True
end
item
Expanded = False
FieldName = 'AName'
Visible = True
end
item
Expanded = False
FieldName = 'AMemo'
Visible = True
end>
end
[...]
object DBNavigator1: TDBNavigator
Left = 16
Top = 216
Width = 240
Height = 25
DataSource = DataSource1
TabOrder = 6
end
object DBMemo1: TDBMemo
Left = 207
Top = 259
Width = 185
Height = 74
DataField = 'AMemo'
DataSource = DataSource1
TabOrder = 7
end
object DBEdit1: TDBEdit
Left = 24
Top = 264
Width = 121
Height = 21
DataField = 'AName'
DataSource = DataSource1
TabOrder = 8
end
object SQLConnection1: TSQLConnection
ConnectionName = 'SQLITECONNECTION'
DriverName = 'Sqlite'
LoginPrompt = False
Params.Strings = (
'DriverName=Sqlite'
'Database=D:\delphi\xe6\sqlite\matestdb.sqlite')
Connected = True
Left = 40
Top = 16
end
object SQLQuery1: TSQLQuery
MaxBlobSize = 1
Params = <>
SQL.Strings = (
'select * from [matable2]')
SQLConnection = SQLConnection1
Left = 128
Top = 16
object SQLQuery1ID: TLargeintField
FieldName = 'ID'
ProviderFlags = [pfInWhere, pfInKey]
end
object SQLQuery1AName: TWideStringField
FieldName = 'AName'
end
object SQLQuery1AMemo: TWideMemoField
FieldName = 'AMemo'
BlobType = ftWideMemo
Size = 1
end
end
object DataSetProvider1: TDataSetProvider
DataSet = SQLQuery1
Options = [poAllowCommandText, poUseQuoteChar]
UpdateMode = upWhereKeyOnly
Left = 216
Top = 16
end
object CDS1: TClientDataSet
Aggregates = <>
CommandText = 'select * from MATable2'
Params = <>
ProviderName = 'DataSetProvider1'
BeforeInsert = CDS1BeforeInsert
AfterInsert = CDS1AfterInsert
BeforePost = CDS1BeforePost
AfterPost = CDS1AfterPost
AfterDelete = CDS1AfterDelete
OnNewRecord = CDS1NewRecord
AfterApplyUpdates = CDS1AfterApplyUpdates
Left = 288
Top = 16
object CDS1ID: TLargeintField
FieldName = 'ID'
end
object CDS1AName: TWideStringField
FieldName = 'AName'
end
object CDS1AMemo: TWideMemoField
FieldName = 'AMemo'
BlobType = ftWideMemo
Size = 1
end
end
object DataSource1: TDataSource
DataSet = CDS1
Left = 344
Top = 16
end
end