Булева переменная, всегда принимающая 1 в select ... into - MySQL - PullRequest
0 голосов
/ 01 июля 2019

Я делаю хранимую процедуру для обновления таблицы, и эта таблица имеет логическое имя: «Завершено», как поле. Это поле информирует нас о завершении игры. В моей задаче имеет смысл установить что-то как завершенное до истечения срока действия, поэтому я проверяю, имеет ли строка для обновления поле «Завершено» как истинное или дата истечения срока действия прошла.

SET @isFinished=0;
SELECT Finished INTO @isFinished FROM game WHERE ID = gameID; 
-- gameID comes as a parameter
-- date comes as a parameter as well
IF DATEDIFF(STR_TO_DATE(date, "%Y-%m-%d") , CURDATE()) < 0  OR @isFinished<>0 THEN
    select CONCAT("Game can't be updated because it's already finished. Days missing:",DATEDIFF( STR_TO_DATE(date, "%Y-%m-%d"), CURDATE() )," and @finished=", @isFinished, ", game=",gameID)
    into @msg;
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = @msg;
END IF;

Проблема в том, что, когда я пытаюсь обновить незаконченную игру, она попадает в if и выдает сообщение об ошибке: "sqlMessage: 'Игра не может быть обновлена, потому что она уже закончена. Дней не хватает: 337 и @ закончено = 1, игра = 2'". быстрое примечание: переменная @isFinished никогда не используется, но в этом блоке кода.

Я всегда уверял, что значение "Finished" было 0 до того, как я его протестировал, и все же он продолжает выбирать его как 1 и, следовательно, попадает в if. Я подумал, что это может быть из select ... into, поэтому я попробовал его из хранимой процедуры (буквально скопировать вставку, просто изменил «gameID» на фактический идентификатор, который я использую), и он работал отлично.

SELECT Finished INTO @isFinished FROM game WHERE ID = 2;
SELECT @isFinished 

После этого я не знаю, что еще я могу проверить. Если бы кто-нибудь мог помочь, я был бы благодарен.

Изолированный тест:

create database test;
use test;

create table Tournament(
    ID int(10) not null unique auto_increment,
    Name varchar(250) not null,
    Start_Date date not null,
    End_Date date not null,
    Primary key(ID)
);

create table Game(
    ID int(10) not null unique auto_increment,
    Tournament_ID int(10),
    Date date,
    Finished boolean,
    Foreign Key(Tournament_ID) references Tournament(ID) ON DELETE CASCADE,
    Primary Key(ID)
);

INSERT INTO Tournament VALUES(NULL, "tournament1", str_to_date("2020-06-01","%Y-%m-%d"), str_to_date("2020-07-01","%Y-%m-%d"));
INSERT INTO Game VALUES(NULL, 1, str_to_date("2020-06-02","%Y-%m-%d"), 0);

DELIMITER $$
DROP PROCEDURE IF EXISTS `UpdateGame`$$
CREATE PROCEDURE `UpdateGame`(IN gameID int, date varchar(10), finished boolean)
BEGIN
SET @isFinished=0;
SELECT Finished INTO @isFinished FROM game WHERE ID = gameID;

IF DATEDIFF(STR_TO_DATE(date, "%Y-%m-%d") , CURDATE()) < 0  OR @isFinished<>0 THEN
    select CONCAT("Game can't be updated because it's already finished. Days missing:",DATEDIFF( STR_TO_DATE(date, "%Y-%m-%d"), CURDATE() )," and @finished=", @isFinished, ", game=",gameID)
    into @msg;
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = @msg;
END IF;
UPDATE game SET Date=STR_TO_DATE(date, "%Y-%m-%d"), Finished=finished WHERE ID=gameID;
END$$
call UpdateGame(1,"2020-06-03",1);

SELECT * FROM game;

SELECT Finished INTO @isFinished FROM game WHERE ID = 1;
SELECT @isFinished;

1 Ответ

0 голосов
/ 01 июля 2019

У вас есть параметр IN Finished, поэтому внутри вашего SP при запросе таблицы вы фактически запрашиваете параметр IN.

Таким образом, вам нужно удалить / переименовать параметр Finished IN или написать свой внутренний запрос выбора как:

SELECT `game`.`Finished` INTO @isFinished FROM game WHERE ID = gameID;

P.S. У людей обычно есть какие-то префиксы во входных параметрах, чтобы визуально отличить их внутри SP от таблиц, столбцов локальных переменных.

...