Столбец данных TINYINT БЕЗ ЗНАКА не может быть минус в предложении where MySQL_8 в macOS

#mysql #where-clause #tinyint

#mysql #where-предложение #tinyint

Вопрос:

Вот данные в MySQL (8.0.x), работающие с macOS:

 ysql> desc t_room;
 -------------- ------------------- ------ ----- --------- ------- 
| Field        | Type              | Null | Key | Default | Extra |
 -------------- ------------------- ------ ----- --------- ------- 
| roomNum      | varchar(60)       | NO   | PRI | NULL    |       |
| roomType     | varchar(20)       | NO   |     | NULL    |       |
| roomDesc     | varchar(400)      | YES  |     | NULL    |       |
| rentPayDay   | tinyint unsigned  | YES  |     | NULL    |       |
| rentFee      | smallint unsigned | NO   |     | NULL    |       |
| asstMine     | varchar(400)      | YES  |     | NULL    |       |
| asstOwner    | varchar(400)      | YES  |     | NULL    |       |
| owner        | varchar(30)       | YES  |     | NULL    |       |
| signDate     | date              | YES  |     | NULL    |       |
| contract     | mediumblob        | YES  |     | NULL    |       |
| roomFacility | varchar(120)      | YES  |     | NULL    |       |
 -------------- ------------------- ------ ----- --------- ------- 
11 rows in set (0.00 sec)

mysql> select rentPayDay from t_room;
 ------------ 
| rentPayDay |
 ------------ 
|         15 |
|         20 |
|         25 |
|         10 |
 ------------ 
4 rows in set (0.00 sec)
  

когда я выполняю запрос с предложением where, как показано ниже, все в порядке:

 mysql> select roomNum, owner, rentPayDay from t_room where rentPayDay - 10 <= 5;
 --------------- -------- ------------ 
| roomNum       | owner  | rentPayDay |
 --------------- -------- ------------ 
| xxxC-906     | John   |         15 |
| xxxxx-908    | Doe   |         10 |
 --------------- -------- ------------ 
2 rows in set (0.00 sec)
  

НО, когда я минус значение, которое может быть больше, чем некоторые значения rentPayDay, например:

 mysql> select roomNum, owner, rentPayDay from t_room where rentPayDay - 11 <= 5;
  

что-то пошло не так, как это:

 ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`dev_learn`.`t_room`.`rentPayDay` - 11)'
  

У кого-нибудь есть какие-либо идеи по этому поводу? почему данные TINYINT не могут минус большее числовое значение в предложении where?

Комментарии:

1. tinyint unsigned означает, что он не может содержать отрицательные (ниже 0) значения. Если ваше вычитание приводит к отрицательному значению, это вызывает эту ошибку.

2. where rentPayDay - 11 <= 5 Никогда не используйте такие условия. Это запрещает использование индекса и вызывает полное сканирование таблицы. По возможности преобразуйте выражение условия в форму {column} {operator} {constant expression} , в которой выражение будет вычисляться во время построения плана выполнения — один раз за весь запрос. Т.е. Выражение должно выглядеть where rentPayDay <= 5 11 дополнительно — проблема с «вне диапазона» не возникнет.

3. @Akina ответ покажите мне способ решения проблемы. Возможно, благодаря вам и вашим напоминаниям.

4. Ответ @KenWhite, я не нашел ни одной ссылки, но я предполагаю {rentPayDay - 11} , что экспресс должен следовать тому же ограничению, что и определение rentPayDay. лучшим и безопасным способом должно быть сравнение rentPayDay с каким-либо другим вычисляемым значением.

Ответ №1:

An UNSIGNED TINYINT имеет диапазон 0-255, и отрицательные значения не могут быть выражены в нем.

Если вы получаете ошибки приведения, рассмотрите:

 SELECT * FROM rooms WHERE CAST(rentPayDay AS DECIMAL) - 11 <= 5;
  

Как показано здесь .

Комментарии:

1. к сожалению, это не решило мою проблему. Большое вам спасибо.

2. Не удается решить. Сначала выполняется вычитание, а не функция. Из-за типа операнда он выполняется как вычисление без знака — и отрицательный результат вызывает ошибку.

3. Я попробовал новый подход. Удивительно раздражает исправление.

4. @Akina показывает правильное направление для этого. моя проблема решается следующим образом: выберите номер комнаты, владельца, rentPayDay из t_room where (rentPayDay >= ИЗВЛЕЧЬ (ДЕНЬ С СЕГОДНЯШНЕГО ДНЯ ())) И (rentPayDay <= ИЗВЛЕЧЬ (ДЕНЬ С ЭТОГО МОМЕНТА()) 5);

5. Это еще одно решение, позволяющее избежать вычитания.

Ответ №2:

со ссылкой на @Akina и @Ken White, вот мое предположение об этой ошибке:

 the express {columnName OPERATOR -value-} still be restricted as a whole with the same definition of {columnName}.
  

Я не знаю, почему и что произошло в ответе MySQL’e на мой запрос.
Лучший способ решить эту проблему:

 please refer to @Akina comment under my original question post.
  

Большое спасибо всем, кто заботится и помогает.