У меня есть 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 раз, тогда я получу результат. Я тоже пробовал со сном (1), но он все еще случайный, когда результат будет нулевым. Только сценарий займет намного больше времени.
Если я попробую блок plsql с 500 попытками, то я получу 500-кратный результат.
Кто-то знает, почему это происходит?
Итак, вы пытаетесь найти результаты с startDate и endDate как == текущее время?
@Gar Запрос не пустой. Всегда заполнял, но ничего не возвращалось. Код не изменился, просто запустите несколько раз. иногда есть результат, иногда нет.
@ArleighHix не совсем startDate и endDate являются границами. Могут быть действительные результаты, которые начинаются раньше, но действительны в промежутке, тогда есть те, которые только между, и те, которые начинаются между и заканчиваются после. Выбор даты работает для многих других таблиц, только эта иногда не выдает результатов
После многих часов тестирования различных сценариев я нашел причину. Это вызвано тем, что 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
Но если сервер оракула не отстает от времени сервера, то это может быть
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
Поскольку sysdate оракула может быть не только больше, но и меньше, могут происходить странные вещи. Поэтому я изменил сравнение sysdate на «sysdate+1», например:
NVL(h.VALIDUNTIL,sysdate+1)
Поскольку это замена значения NULL, возможно, что в будущем это все равно приведет к желаемым результатам.
Вы проверили, что $query не равен нулю ?? может быть, вы пропустили подключение к базе данных