Sql 左联接查询的where子句中的存储过程可能会获取NULL参数

Sql 左联接查询的where子句中的存储过程可能会获取NULL参数,sql,stored-procedures,subquery,firebird,Sql,Stored Procedures,Subquery,Firebird,我在Firebird 2.5中执行查询时遇到了奇怪的情况: select ps.ProductId, p.Id, p.DefPurcUOMNr, p.IsStockFlag from ProductSupplier ps left join Product p on p.Id = ps.ProductId where (select q.Qty from ProductQtyBMUToUOM$(p.Id, p.DefPurcUOMNr, 1) as q) > 0

我在Firebird 2.5中执行查询时遇到了奇怪的情况:

select ps.ProductId, p.Id, p.DefPurcUOMNr, p.IsStockFlag 
  from ProductSupplier ps left join 
    Product p on p.Id = ps.ProductId 
where 
  (select q.Qty from ProductQtyBMUToUOM$(p.Id, p.DefPurcUOMNr, 1) as q) > 0 
上面的查询工作正常,但如果add p.IsStockFlag=1,则对于p.IsStockFlag=0的记录,存储的proc productqtybmutoom$的p.Id、p.DefPurcUOMNr参数将传递等于NULL

我想这是正确的行为,但我找不到好的描述。只有我的猜测是基于这个观察的


提前感谢大家。

我没有看到关于p.IsStockFlag的任何标准。你的意思是说以下内容吗

select ps.ProductId, p.Id, p.DefPurcUOMNr, p.IsStockFlag 
  from ProductSupplier ps left join 
    Product p on p.Id = ps.ProductId 
where 
  p.IsStockFlag>0 and
  (select q.Qty from ProductQtyBMUToUOM$(p.Id, p.DefPurcUOMNr, 1) as q) > 0 

我没有看到任何关于p.IsStockFlag的标准。你的意思是说以下内容吗

select ps.ProductId, p.Id, p.DefPurcUOMNr, p.IsStockFlag 
  from ProductSupplier ps left join 
    Product p on p.Id = ps.ProductId 
where 
  p.IsStockFlag>0 and
  (select q.Qty from ProductQtyBMUToUOM$(p.Id, p.DefPurcUOMNr, 1) as q) > 0 
使用左联接时,第二个条件的条件应位于on子句中:

你说where子句可以正常工作,所以我把它留下了。我倾向于将其移动到on子句,甚至将其作为单独的联接。

当使用左联接时,第二个条件的条件应该在on子句中:


你说where子句可以正常工作,所以我把它留下了。我倾向于将其移动到on子句,甚至将其作为单独的联接。

哦,对不起,是的,我的意思是p.IsStockFlag>0and@NikitaParhimchik然后也许编辑你的问题以显示真实的代码,没有错误?哦,对不起,是的,我的意思是p.IsStockFlag>0and@NikitaParhimchik然后也许编辑你的问题以显示真正的代码,没有错误?您的查询设置了左联接乘积p,这意味着对于ps关系中的许多行,p关系的所有列都将为空-这就是左联接与对称内部联接的区别定义。因此,如果您需要很好的描述,那么只需阅读任何SQL入门级书籍,了解什么是内部连接、左连接、右连接。此外,从SP中进行单独的选择在这里看起来是多余的。只需取消对FROM/JOIN部分的SP调用,就像它是另一个过程@Arioch',这意味着where子句在记录加入之前过滤记录我想首先选择记录集,然后使用where中的条件进行过滤。非常感谢。@Arioch'如果我将条件p.IsStockFlag=1添加到它等于的位置,我将把它添加到ProductSupplier ps left的连接条件中,在p.Id=ps.ProductId和p.IsStockFlag=1 Right上连接产品p?基本上SQL优化器可能会得到任何不同的查询计划,理论上应该返回相同的集。RDMBS基于数学集合抽象,所有子句都是集合产生的过滤器。只要某个操作产生相同的子集,它就是正确的。这意味着,根据表中的特定数据,同一服务器中的同一查询可能由不同的查询计划执行。SQL server对您来说是一个黑匣子,它会给您带来一些巫术般的效果。将您的程序绑定到voodoo的实现细节是不安全的,您的查询将设置左连接产品p,这意味着对于ps关系中的许多行,p关系的所有列都将为空-这就是左连接与对称内部连接的不同定义。因此,如果您需要很好的描述,那么只需阅读任何SQL入门级书籍,了解什么是内部连接、左连接、右连接。此外,从SP中进行单独的选择在这里看起来是多余的。只需取消对FROM/JOIN部分的SP调用,就像它是另一个过程@Arioch',这意味着where子句在记录加入之前过滤记录我想首先选择记录集,然后使用where中的条件进行过滤。非常感谢。@Arioch'如果我将条件p.IsStockFlag=1添加到它等于的位置,我将把它添加到ProductSupplier ps left的连接条件中,在p.Id=ps.ProductId和p.IsStockFlag=1 Right上连接产品p?基本上SQL优化器可能会得到任何不同的查询计划,理论上应该返回相同的集。RDMBS基于数学集合抽象,所有子句都是集合产生的过滤器。只要某个操作产生相同的子集,它就是正确的。这意味着,根据表中的特定数据,同一服务器中的同一查询可能由不同的查询计划执行。SQL server对您来说是一个黑匣子,它会给您带来一些巫术般的效果。将程序绑定到voodoo的实现细节是不安全的
select ps.ProductId, p.Id, p.DefPurcUOMNr, p.IsStockFlag 
from ProductSupplier ps left join 
     Product p
     on p.Id = ps.ProductId and p.IsStockFlag = 1
where (select q.Qty from ProductQtyBMUToUOM$(p.Id, p.DefPurcUOMNr, 1) as q) > 0 ;