mORMot2 获取数据集1
mORMot2 获取数据集
其实在前面想学习mORMot1部分已经收集了很多关于CRUD的示例了,但感觉总是不通透,不能很好使用,一则mORMot函数命令规则比较不同寻常,另外确实示例太少,其实代码注释倒是讲了很多。
procedure FillPrepare(Table: TOrmTable; aCheckTableName: TOrmCheckTableName = ctnNoCheck); overload;
FillPrepare
程序是为了从 TOrmTable
结果中准备获取值。
- 在准备之后,你可以调用
FillRow(1..Table.RowCount)
来获取任何一行的值。 - 或者,你也可以使用以下循环来遍历所有行:
while Rec.FillOne do
dosomethingwith(Rec);
- 在这个过程中,指定的
TOrmTable
被存储在一个受保护的内部字段fTable
中。 - 如果你想获取表中的字段名,可以设置
aCheckTableName
参数。在匹配到当前记录之前,任何待处理的'TableName.'
前缀都将被去除。
注意:这里的 dosomethingwith(Rec);
是一个占位符,代表你可以对每一行记录 Rec
执行某些操作。实际使用时,你需要将其替换为具体的业务逻辑代码。同时,Rec
应该是一个已经定义好的记录类型变量,用于存储从 TOrmTable
中获取的数据。
另外,TOrmCheckTableName
是一个枚举类型,ctnNoCheck
是它的一个值,表示不进行表名检查。如果你需要检查表名,可以传递其他相应的枚举值给 aCheckTableName
参数。
function FillPrepare(const aClient: IRestOrm; const aSqlWhere: RawUtf8 = ''; const FieldsCsv: RawUtf8 = ''; aCheckTableName: TOrmCheckTableName = ctnNoCheck): boolean; overload;
FillPrepare
函数用于从 SQL WHERE 语句中获取值。
- 如果 SQL 请求成功,则返回 true,如果在 SQL 请求期间发生错误,则返回 false。
- 准备完成后,你可以通过调用
FillRow(1..Table.RowCount)
来获取任何一行的值。 - 或者,你也可以使用以下循环来遍历所有行:
while Rec.FillOne do
dosomethingwith(Rec);
- 函数会创建一个临时的
TOrmTable
,并将其存储在一个受保护的内部字段fTable
中。 - 如果
aSqlWhere
留空(''),则会尽快检索所有行(例如,通过绕过外部数据库的 SQLite3 虚拟表模块)。 - WHERE 子句应使用内联参数(如
'Name=:('Arnaud'):'
)以提高服务器速度。请注意,你可以像这样使用FormatUtf8()
:
aRec.FillPrepare(Client, FormatUtf8('Salary>? AND Salary<?', [], [1000, 2000]));
或者直接使用带有 BoundsSqlWhere
参数数组的 FillPrepare()
方法的重载版本。
FieldsCsv
可用于指定必须检索哪些字段。- 默认的
FieldsCsv=''
将检索所有简单的表字段,但如果你只需要访问一个或多个字段,并希望节省远程带宽,可以通过指定所需字段来实现。 - 如果
FieldsCsv='*'
,它将检索所有字段,包括 BLOBs。 - 请注意,如果你想稍后更新检索到的记录内容,则不应使用此可选的
FieldsCsv
参数,因为任何缺失的字段都将保留先前的值。但是,在FillPrepare
之后可以安全地使用BatchUpdate()
(将仅设置 ID、TModTime 和映射的字段)。
function FillPrepare(const aClient: IRestOrm; const FormatSqlWhere: RawUtf8; const BoundsSqlWhere: array of const; const FieldsCsv: RawUtf8 = ''): boolean; overload;
使用带有 '%' 参数的指定 WHERE 子句准备获取值。
- 如果 SQL 请求成功,则返回 true,如果在 SQL 请求期间发生错误,则返回 false。
- 准备完成后,你可以通过调用
FillRow(1..Table.RowCount)
来获取任何一行的值。 - 或者,你也可以使用以下循环来遍历所有行:
while Rec.FillOne do
dosomethingwith(Rec);
- 函数会创建一个临时的
TOrmTable
,并将其存储在一个受保护的内部字段fTable
中。 - 为了提高服务器速度,WHERE 子句应使用在
FormatSqlWhere
语句中标识为 '?' 的绑定参数,这些参数应按照BoundsSqlWhere
开放数组中提供的值的顺序进行排列。对于TDateTime
类型,使用DateToSql
/DateTimeToSql
,或者直接将任何整数/双精度/货币/RawUtf8 值绑定为请求的参数。 - 请注意,此方法原型在框架的 1.17 版中已更改:以前
ParamsSqlWhere
是array of const
类型,并在FormatSqlWhere
语句中使用 '%',而现在它期望绑定参数为 '?'。 FieldsCsv
可用于指定必须检索哪些字段。- 默认的
FieldsCsv=''
将检索所有简单的表字段,但如果你只需要访问一个或多个字段,并希望节省远程带宽,可以通过指定所需字段来实现。 - 如果
FieldsCsv='*'
,它将检索所有字段,包括 BLOBs。 - 请注意,如果你想稍后更新检索到的记录内容,则不应使用此可选的
FieldsCsv
参数,因为任何缺失的字段都将保留先前的值。但是,在FillPrepare
之后可以安全地使用BatchUpdate()
(将仅设置 ID、TModTime 和映射的字段)。
function FillPrepare(const aClient: IRestOrm; const FormatSqlWhere: RawUtf8; const ParamsSqlWhere, BoundsSqlWhere: array of const; const FieldsCsv: RawUtf8 = ''): boolean; overload;
使用带有 '%' 和 '?' 参数的指定 WHERE 子句准备获取值。
- 如果 SQL 请求成功,则返回 true,如果在 SQL 请求期间发生错误,则返回 false。
- 准备完成后,你可以通过调用
FillRow(1..Table.RowCount)
来获取任何一行的值。 - 或者,你也可以使用以下循环来遍历所有行:
while Rec.FillOne do
dosomethingwith(Rec);
- 函数会创建一个临时的
TOrmTable
,并将其存储在一个受保护的内部字段fTable
中。 FormatSqlWhere
子句会将所有 '%' 字符替换为提供的ParamsSqlWhere[]
数组中的值,并将所有 '?' 字符绑定为BoundsSqlWhere[]
数组中的绑定参数值。FieldsCsv
可用于指定必须检索哪些字段。- 默认的
FieldsCsv=''
将检索所有简单的表字段,但如果你只需要访问一个或多个字段,并希望节省远程带宽,可以通过指定所需字段来实现。 - 如果
FieldsCsv='*'
,它将检索所有字段,包括 BLOBs。 - 请注意,如果你想稍后更新检索到的记录内容,则不应使用此可选的
FieldsCsv
参数,因为任何缺失的字段都将保留先前的值。但是,在FillPrepare
之后可以安全地使用BatchUpdate()
(将仅设置 ID、TModTime 和映射的字段)。
这个函数结合了两种参数替换方式:'%' 字符的直接替换和 '?' 的绑定参数方式,为用户提供了更大的灵活性。但同时,也要求用户更仔细地管理参数以避免潜在的 SQL 注入风险。
function FillPrepare(const aClient: IRestOrm; const aIDs: array of TID; const FieldsCsv: RawUtf8 = ''): boolean; overload;
准备从一个ID列表中获取值。
- 如果SQL请求成功,则返回true,如果SQL请求期间出现错误,则返回false。
- 准备完成后,你可以通过调用
FillRow(1..Table.RowCount)
来获取任何一行的值。 - 或者,你也可以使用以下循环来遍历所有行:
while Rec.FillOne do
dosomethingwith(Rec);
- 函数会创建一个临时的
TOrmTable
,并将其存储在一个受保护的内部字段fTable
中。 FieldsCsv
可用于指定必须检索哪些字段。- 默认的
FieldsCsv=''
将检索所有简单的表字段,但如果你只需要访问一个或多个字段,并希望节省带宽,可以通过指定所需字段来实现。 - 如果
FieldsCsv='*'
,它将检索所有字段,包括BLOBs。 - 请注意,如果你想稍后更新检索到的记录内容,则不应使用此可选的
FieldsCsv
参数,因为任何缺失的字段都将保留先前的值。但在FillPrepare
之后可以安全地使用BatchUpdate()
(只会设置ID、TModTime和映射的字段)。
这个重载版本的 FillPrepare
函数接收一个ID数组作为参数,使得用户能够一次性检索多个特定ID对应的记录,提高了数据检索的效率。同时,与上一个版本类似,它也支持通过 FieldsCsv
参数来定制需要检索的字段,以满足不同的数据需求。
function FillPrepareMany(const aClient: IRestOrm; const aFormatSQLJoin: RawUtf8; const aParamsSQLJoin, aBoundsSQLJoin: array of const): boolean;
准备遍历包含 TOrmMany
字段的JOIN语句。
- 所有
TOrmMany.Dest
发布的字段现在将包含一个真正的TOrm
实例,准备好用JOIN语句的结果填充(这些实例将在FillClose
时释放)——Source
也将指向自身实例。 aFormatSQLJoin
子句将为自动化的JOIN语句定义一个WHERE子句,包括TOrmMany
发布的属性(及其嵌套属性)。- 如果SQL请求成功,则返回true,如果SQL请求期间出现错误,则返回false。
- 一个典型的应用场景可能如下:
if aProd.FillPrepareMany(Database,
'Owner=? and Categories.Dest.Name=? and (Sizes.Dest.Name=? or Sizes.Dest.Name=?)',
[], ['mark', 'for boy', 'small', 'medium']) then
while aProd.FillOne do
// 在这里,例如,aProd.Categories.Dest被实例化(并且Categories.Source=aProd)
writeln(aProd.Name, ' ', aProd.Owner, ' ', aProd.Categories.Dest.Name, ' ', aProd.Sizes.Dest.Name);
// 你也可以使用aProd.FillTable来填充一个网格,例如
// (不要忘记设置aProd.FillTable.OwnerMustFree := false)
这将执行类似于以下的JOIN SELECT语句:
select p.*, c.*, s.*
from Product p, Category c, Categories cc, Size s, Sizes ss
这个函数允许用户准备和执行复杂的JOIN查询,同时自动处理 TOrmMany
关系。通过这种方式,用户可以方便地获取相关联的数据,并在应用程序中进行进一步处理。此函数还提供了参数化查询的功能,增强了查询的灵活性和安全性。