it-swarm.dev

Dane obcięte dla kolumny

DECLARE float_one, float_two, my_result NUMERIC(7,2)    
my_result = CONVERT(float_one/float_two, DECIMAL(7,2));

W tym zapytaniu mysql wykonuję operacje tego typu w procedurze przechowywanej, ale środowisko phpmyadmin w środowisku Linux wyświetla następujące ostrzeżenie:

Uwaga: # 1265 Dane obcięte dla kolumny „float_one” w wierszu 5

Czy ktoś ma pomysł, jak mogę rozwiązać ten problem?

CREATE TABLE IF NOT EXISTS `float_sample` (
      `id` int(11) NOT NULL auto_increment,
      `first_number` float(10,3) default NULL,
      `second_number` float(10,3) default NULL,
      PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

INSERT INTO `float_sample` (`id`, `first_number`, `second_number`) 
VALUES    (1, 2.900, 1.900),    (2, 3.100, 22.100);

i procedura

DELIMITER $$
DROP PROCEDURE IF EXISTS float_test$$
CREATE PROCEDURE float_test(IN my_ID INT)  

BEGIN
DECLARE first_float, second_float DECIMAL(10,3);

DECLARE done INT DEFAULT 0;

DECLARE myCursor CURSOR FOR 
        SELECT `first_number`, `second_number`
        FROM `float_sample`
        WHERE `id` = my_ID;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN myCursor;
my_loop:LOOP
    FETCH myCursor INTO first_float, second_float;

    IF done = 1 THEN
        LEAVE my_loop;
    END IF;

END LOOP my_loop;
CLOSE myCursor;

-- SELECT first_float, second_float;
END;$$
DELIMITER ;

i wynik

1 70 10:41:36    CALL mytests.float_test(1) 0 row(s) affected, 2 warning(s):
1265 Data truncated for column 'first_float' at row 2
1265 Data truncated for column 'second_float' at row 2  0.032 sec
6
dole doug

Jaka jest wartość float_one w momencie konwersji ???

Zwróć uwagę na ten przykład z MySQL 5.5.12 w systemie Windows

mysql> select convert(20000,decimal(7,2));
+-----------------------------+
| convert(20000,decimal(7,2)) |
+-----------------------------+
|                    20000.00 |
+-----------------------------+
1 row in set (0.00 sec)

mysql> select convert(200000,decimal(7,2));
+------------------------------+
| convert(200000,decimal(7,2)) |
+------------------------------+
|                     99999.99 |
+------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------------------------------+
| Level   | Code | Message                                                               |
+---------+------+-----------------------------------------------------------------------+
| Warning | 1264 | Out of range value for column 'convert(200000,decimal(7,2))' at row 1 |
+---------+------+-----------------------------------------------------------------------+

1 row in set (0.00 sec)

Możliwe, że dane zostały obcięte, jeśli liczba większa niż 999,99 była w float_one. Być może mysql konwertuje indywidualnie float_one i float_two na DECIMAL (7,2) indywidualnie przed wykonaniem podziału. Spróbuj użyć DECIMAL (10,2) lub wyższej, aby uwzględnić duże wartości.

AKTUALIZACJA 2011-07-25 15:05 EDT

Występuje tutaj wyraźny problem obcięcia

Zgodnie z MySQL Reference Manual Page 442 Akapity 2,

Wartości DECIMAL i NUMERIC są przechowywane jako ciągi, a nie jako binarne liczby zmiennoprzecinkowe, aby zachować dokładność dziesiętną tych liczb. Dla każdej cyfry wartości stosuje się jeden znak, punkt deciamlowy (jeśli skala> 0) i znak - (dla liczb ujemnych). Jeśli skala wynosi 0, wartości dziesiętne i liczbowe nie zawierają kropki dziesiętnej ani części ułamkowej.

Maksymalny zakres DECIMAL i NUMERIC jest taki sam, jak w przypadku DOUBLE, ale rzeczywisty zakres dla danej kolumny DECIMAL lub NUMERIC może być ograniczony precyzją i skalą dla podanej kolumny, gdy takiej kolumnie zostanie przypisana wartość z następującymi po niej cyframi przecinek dziesiętny, niż dopuszcza określona skala, wartość jest zaokrąglana do tej skali. Gdy kolumna DECIMAL lub NUMERIC zostanie przypisana wartość, której wielkość przekracza zakres wynikający z określonej (lub domyślnej) precyzji i skali, MySQL przechowuje wartość reprezentującą odpowiedni punkt końcowy tego zakresu.

Musisz uwzględnić większą precyzję i/lub skalę.

Oto przykład, dlaczego

Napisałem tę procedurę przechowywaną przy użyciu twoich specyfikacji dla DECMIAL i NUMERIC.

DELIMITER $$

DROP PROCEDURE IF EXISTS `test`.`NumTest` $$
CREATE PROCEDURE `test`.`NumTest` (num1 NUMERIC(7,2), num2 NUMERIC(7,2))
BEGIN

  DECLARE float_one,float_two,my_result NUMERIC(7,2);
  DECLARE f1,f2 DOUBLE(7,2);

  SET f1 = num1;
  SET f2 = num2;

  SET float_one = num1;
  SET float_two = num2;

  SELECT f1 / f2;
  SELECT float_one / float_two;
  SELECT CONVERT(float_one / float_two,DECIMAL(7,2));
  SET my_result = CONVERT(float_one / float_two,DECIMAL(7,2));
  SELECT my_result;

END $$

DELIMITER ;

Do tego testu użyłem dwóch wartości: 290,0 i 14,5.

Przed wywołaniem procedury składowanej NumTest ręcznie obliczyłem 290,0/14,5

mysql> select 290.0 / 14.5;
+--------------+
| 290.0 / 14.5 |
+--------------+
|     20.00000 |
+--------------+
1 row in set (0.00 sec)

Podzieliłem każdą liczbę przez 100, 10000 i 1000000 i spróbowałem ponownie

mysql> select 2.9 / .145;
+------------+
| 2.9 / .145 |
+------------+
|   20.00000 |
+------------+
1 row in set (0.00 sec)

mysql> select .029 / .00145;
+---------------+
| .029 / .00145 |
+---------------+
|    20.0000000 |
+---------------+
1 row in set (0.00 sec)

mysql> select .00029 / .0000145;
+-------------------+
| .00029 / .0000145 |
+-------------------+
|      20.000000000 |
+-------------------+
1 row in set (0.00 sec)

Na razie w porządku !!! Teraz procedura składowana.

mysql> call numtest(290.0,14.5);
+-----------+
| f1 / f2   |
+-----------+
| 20.000000 |
+-----------+
1 row in set (0.00 sec)

+-----------------------+
| float_one / float_two |
+-----------------------+
|             20.000000 |
+-----------------------+
1 row in set (0.00 sec)

+---------------------------------------------+
| CONVERT(float_one / float_two,DECIMAL(7,2)) |
+---------------------------------------------+
|                                       20.00 |
+---------------------------------------------+
1 row in set (0.00 sec)

+-----------+
| my_result |
+-----------+
|     20.00 |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Więc moje dwie oryginalne liczby działają dobrze. Podzielmy je przez 100 i spróbuj ponownie.

mysql> call numtest(2.9,0.145);
+-----------+
| f1 / f2   |
+-----------+
| 19.333333 |
+-----------+
1 row in set (0.00 sec)

+-----------------------+
| float_one / float_two |
+-----------------------+
|             19.333333 |
+-----------------------+
1 row in set (0.00 sec)

+---------------------------------------------+
| CONVERT(float_one / float_two,DECIMAL(7,2)) |
+---------------------------------------------+
|                                       19.33 |
+---------------------------------------------+
1 row in set (0.00 sec)

+-----------+
| my_result |
+-----------+
|     19.33 |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------+
| Level | Code | Message                                   |
+-------+------+-------------------------------------------+
| Note  | 1265 | Data truncated for column 'num2' at row 2 |
+-------+------+-------------------------------------------+
1 row in set (0.00 sec)

CZEKAJ, straciliśmy trochę precyzji. Co się stało ??? Jak to się stało ??? Musisz zmieścić więcej cyfr dziesiętnych (> 2)

AKTUALIZACJA 2011-07-25 17:37 EDT

Zastąpiłem (7,2) (10,7) w procedurze przechowywanej i odzyskałem odpowiednią precyzję

mysql> call numtest(2.9,0.145);
+----------------+
| f1 / f2        |
+----------------+
| 20.00000000000 |
+----------------+
1 row in set (0.00 sec)

+-----------------------+
| float_one / float_two |
+-----------------------+
|        20.00000000000 |
+-----------------------+
1 row in set (0.01 sec)

+----------------------------------------------+
| CONVERT(float_one / float_two,DECIMAL(10,7)) |
+----------------------------------------------+
|                                   20.0000000 |
+----------------------------------------------+
1 row in set (0.03 sec)

+------------+
| my_result  |
+------------+
| 20.0000000 |
+------------+
1 row in set (0.05 sec)

Query OK, 0 rows affected (0.06 sec)

mysql>
3
RolandoMySQLDBA

Z tego, co widzę, twoja procedura przechowywana po prostu pętli przez wiersze - nigdzie nie „zapisuje danych” i skomentowałeś select:

- SELECT first_float, second_float;

Tak, otrzymujesz ostrzeżenia, gdy pola float(10,3) są konwertowane na decimal(10,3). To, czy stanowią problem, czy nie, zależy od tego, co chcesz zrobić z polami.

Czy to tylko próbka prawdziwego kodu? Być może będziesz musiał opublikować więcej ...