我有一个sql,它应该给我一个列表,但有时结果为空。它是随机发生的。用户,版本或其他任何内容都没有改变。另一个请求有时是空的。
有一个数据库表,该表具有用于历史记录值的触发器。 如果插入新行,则在历史记录表中将创建新行。对于新表,有一个“ validFrom”列,该列将设置为sysdate。 如果已更新,则旧行将设置为“ validUntil”,并插入新行。 该表在SUB_ID上有一个索引。
该表没有实例化视图或视图。只是一张普通桌子。
SQL
SELECT h.ID, h.SUB_ID
FROM history h
WHERE 1=1
AND h.SUB_ID = :subId
AND (
1=1
AND (
TO_DATE(:startDate, 'YYYY-MM-DD HH24:MI:SS') >= h.VALIDFROM
AND TO_DATE(:startDate, 'YYYY-MM-DD HH24:MI:SS') <= NVL(h.VALIDUNTIL,sysdate)
) OR (
TO_DATE(:startDate, 'YYYY-MM-DD HH24:MI:SS') <= h.VALIDFROM
AND TO_DATE(:endDate, 'YYYY-MM-DD HH24:MI:SS') >= NVL(h.VALIDUNTIL,sysdate)
) OR (
TO_DATE(:endDate, 'YYYY-MM-DD HH24:MI:SS') >= h.VALIDFROM
AND TO_DATE(:endDate, 'YYYY-MM-DD HH24:MI:SS') <= NVL(h.VALIDUNTIL,sysdate)
)
)
PHP
$validFrom = new Datetime();
$validUntil = new Datetime();
$query = $this->db->prepare($query);
$query->bindValue('subId', 20180101123456789, PDO::PARAM_STR);
$query->bindValue('startDate', $validFrom->format('Y-m-d H:i:s'), PDO::PARAM_STR);
$query->bindValue('endDate', $validUntil->format('Y-m-d H:i:s'), PDO::PARAM_STR);
$query->execute();
$result = $query->fetchAll();
$ result有时为空,有时会有结果。我唯一的解决方法是尝试多达500次,然后得到结果。 我也尝试过sleep(1),但是当结果为null时它仍然是随机的。只有脚本会花费更长的时间。
如果我尝试使用500次尝试的plsql块,那么我将得到500倍的结果。
有人知道为什么会这样吗?
答案 0 :(得分:1)
经过数小时的不同场景测试,我找到了原因。 这是由于oracle sysdate可能早于php datetime。
人们期望:
php new Datetime()->format('Y-m-d H:i:s') = 2019-06-05 12:55:00
oracle to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') >= 2019-06-05 12:55:00
但是,如果oracle服务器的服务器时间不足,则可能是
php new Datetime()->format('Y-m-d H:i:s') = 2019-06-05 12:55:00
oracle to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') <=> 2019-06-05 12:55:00
由于oracle sysdate不仅可能更大,而且会更小,所以可能会发生一些奇怪的事情。因此,我将sysdate的名称改为“ sysdate + 1”:
NVL(h.VALIDUNTIL,sysdate+1)
由于它是NULL值的替代,因此有可能在将来出现,但仍会产生想要的结果。