Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Delphi TSQLDataSet无SQL内部联接查询输出_Sql Server_Delphi_Inner Join_Delphi Xe4 - Fatal编程技术网

Sql server Delphi TSQLDataSet无SQL内部联接查询输出

Sql server Delphi TSQLDataSet无SQL内部联接查询输出,sql-server,delphi,inner-join,delphi-xe4,Sql Server,Delphi,Inner Join,Delphi Xe4,我使用TSQLConnection和TSQLDataSet从Delphi应用程序查询SQL server(2012)数据库。到目前为止,我的所有查询都工作得很好,但是我现在正试图编写一个带有内部联接的SELECT查询,并且我无法访问TSQLDataSet的任何输出 守则: Query_text:='SELECT Table1.Price 'FROM [Table1] 'INNER JOIN [Table2] 'ON

我使用TSQLConnection和TSQLDataSet从Delphi应用程序查询SQL server(2012)数据库。到目前为止,我的所有查询都工作得很好,但是我现在正试图编写一个带有内部联接的SELECT查询,并且我无法访问TSQLDataSet的任何输出

守则:

Query_text:='SELECT Table1.Price
            'FROM [Table1]
              'INNER JOIN [Table2]
              'ON Table1.Code_ID = Table2.ID'   
            'WHERE (Table2.Code = '+QuotedStr(Temp_code)+')';

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;
SQL_dataset.Open;  

If SQL_dataset.RecordCount>0 then .... { THIS RETURNS NOTHING }
如果我将此查询输入到SSMS,则返回正确的信息。在我使用的所有其他SELECT查询(没有内部联接)中,SQL_dataset按预期返回recordcount和FieldName

有没有关于问题是什么以及如何解决的想法

更新:

我在TSQLDataset.RecordCount上的信息:

从这一点上,我没有得到这样的印象:它不适用于简单的查询——到目前为止,我已经成功地将它用于简单的SELECT查询,作为查询是否返回任何数据的标志……我是幸运的吗?但是,上面的链接指出它不能用于参数化查询和多表联接,因此这似乎可以解释我原来的问题!所以非常感谢你为我指明了正确的方向

此链接表明,如果Bof和Eof均为真,则结果集为空:

这是更好的选择吗

更新2:

谢谢你的解释,我开始明白了。我已经删除了对RecordCount的所有引用,并按照建议用TSQLDataset.isEmpty替换(我完全错过了该方法,谢谢)

我原以为只要调用TSQLDataset.Open,就会填充TSQLDataset.RecordCount,但如果我理解正确,情况不是这样吗

在某些情况下,我会滚动浏览结果,如下所示:

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;
SQL_dataset.Open;

If SQL_dataset.IsEmpty=False then 
begin
  SQL_dataset.First;

  While not SQL_dataset.Eof do  
  begin
    { DO SOMETHING }
    SQL_dataset.Next;
  end;
end;

这显然调用了TSQLDataset.Next,所以我假设它会执行您所讨论的所有内存缓冲(根据记录计数)。这到底发生在什么时候

这是用于文件(如DBF和CSV)的代码,而不是用于SQL远程数据集的代码

1) 不保证
RecordCount
包含除本地文件以外的任何有用信息。如果会-这意味着所有数据都从mremote服务器读取到本地客户机内存。调用SQL的
RecordsCount
意味着“我希望我的应用程序冻结一个小时,直到所有数据库内容从服务器拉到客户端,然后由于“内存不足”错误而崩溃”。使用属性
.Empty
.BOF
.EOF

实际上,你从哪里得到的
RecordCount
???当您阅读文档时,确实看到文档明确指出
RecordCount
与数据库中的记录数不对应,因此检查
RecordCount
>0是否与数据库数据无关。

2) 使用参数

试着这样做:

with SQL_dataset do begin
     Close;
     CommandType := ctQuery;
     ParamCheck := true;
     CommandText := 'SELECT Table1.Price FROM "Table1"  ' +
          'INNER JOIN "Table2" ON Table1.Code_ID = Table2.ID  '   +
          'WHERE Table2.Code = :Temp_code ';
     Params[0].AsString := 'abcdefgh';
     Open;

     if not IsEmpty then begin
....
     end;
end;
另外,请编辑问题的标签,并指定Delphi版本和指定数据库访问驱动程序


更新:

关于

if SQL_dataset.Bof=True and SQL_dataset.Eof=True then  
begin 
  Found:=False;
这可以写得更简单

Found := not (SQL_dataset.Bof and SQL_dataset.Eof)
或者在现代德尔菲

Found := not SQL_dataset.IsEmpty;


我没有得到这样的印象,一个简单的查询是行不通的

您无法可靠地区分简单查询和复杂查询。如果XXX是一个存储过程、视图或表,其中某些列是由子查询计算的虚拟数据,则SELECT*FROM XXX可能是一个非常复杂的查询

也重读我上面写的。获取最终记录数意味着服务器应该执行查询到最后。网络应将所有数据传输到终端。而
TDataSet
应该将所有接收到的数据缓存到内存中,这样您就可以调用
。Next

想象一下,在一个简单的表上进行一个简单的查询,该表包含10万行,每行1000字节(如客户机的名称+照片),总计接近10 GB。考虑典型的100 Mb/s(大约10 Mb/s)网络。传输所有这些数据需要多长时间才能了解它们的计数?在大约2Gb的传输量下,32位应用程序将因内存不足而死掉。 当你真的想知道是否至少有一行或者没有行时,所有的负载都会增加

更新2

作为。在执行
之前检查
.IsEmpty
,同时。。。EOF对我来说似乎有点过于工程化了。在这些情况下,当数据集实际上是空的,而循环将退出w/o并进入迭代体时。所以,就个人而言,如果您没有一个else分支具有空数据集的特定代码路径,那么可以在删除这样的循环之前进行这样的检查

至于缓存。。。这很难确定。通常有一个链条:
数据库文件->数据库服务器+查询->数据库访问库->数据集->网格或其他使用者

在每个箭头处,可能会发生一些缓存,也可能不会发生

还有单向和双向SQL查询/游标。 对于双向,您可以任意选择
.Next
.previor
。这对于网格非常有用。然而,对于服务器来说,这意味着要么缓存所有内部行ID,直到游标(查询)关闭,要么引擎和索引自然允许在两个方向上进行查询。我敢打赌,数据库服务器的数据结构和算法的自然优化选择选择了前一种方法。至少我不会认为后者是一个可靠的隐含假设。

如果TDataSet也是单向的,或者TDataSet和底层library+服务器都是双向的,那么TDataSet会将数据缓存成小块。我估计有十几排。它将创建额外的冗余网络往返,以便将每一行作为单独的请求获取。但它也会对网络造成不必要的负担(因此延迟),以获取数百或数千

TDbGrid通常不缓存自身,而是
Found := not SQL_dataset.IsEmpty;