it-swarm-eu.dev

Data zkrácena pro sloupec

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

V tomto dotazu mysql provádím tento typ operace v uložené proceduře, ale Linuxové prostředí phpmyadmin vyvolá následující varování:

Poznámka: # 1265 Data zkrácená pro sloupec 'float_one' v řádku 5

Má někdo představu, jak mohu tento problém vyřešit?

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);

a postup

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 ;

a výsledek

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

Jaká je hodnota float_one v době převodu ???

Všimněte si tohoto příkladu z MySQL 5.5.12 ve 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)

Je možné, že data byla zkrácena, pokud bylo číslo float_one větší než 99999,99. Možná, mysql převáděl float_one a float_two na DECIMAL (7,2) individuálně před provedením dělení. Zkuste použít DECIMAL (10,2) nebo vyšší, aby se přizpůsobily velkým hodnotám.

AKTUALIZACE 2011-07-25 15:05 EDT

Zde se děje určitý problém se zkrácením

Podle MySQL Reference Manual Strana 442 Body 2,

Hodnoty DECIMAL a NUMERIC se ukládají spíše jako řetězce než jako binární čísla s pohyblivou řádovou čárkou, aby se zachovala desetinná přesnost těchto čísel. Jeden znak se používá pro každou číslici hodnoty, deciaml bod (pokud je měřítko> 0) a znaménko - (pro záporná čísla). Pokud je měřítko 0, hodnoty DECIMAL a NUMERIC neobsahují žádné desetinné tečky nebo zlomkovou část.

Maximální rozsah DECIMAL a NUMERIC je stejný jako pro DOUBLE, ale skutečný rozsah pro daný sloupec DECIMAL nebo NUMERIC může být omezen přesností a měřítkem pro daný sloupec. Když je tomuto sloupci přiřazena hodnota s více číslicemi po desetinná tečka, než je povoleno určeným měřítkem, je hodnota zaokrouhlena na toto měřítko. Když je sloupci DECIMAL nebo NUMERIC přiřazena hodnota, jejíž velikost přesahuje rozsah implikovaný specifikovanou (nebo výchozí) přesností a měřítkem, MySQL ukládá hodnotu představující odpovídající koncový bod tohoto rozsahu.

Musíte se přizpůsobit větší přesnosti a/nebo měřítku.

Zde je příklad, proč

Tuto uloženou proceduru jsem napsal pomocí vašich specifikací pro DECMIAL a 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 ;

Pro tento test jsem použil dvě hodnoty: 290,0 a 14,5.

Před voláním uložené procedury NumTest jsem vypočítal ručně 290,0/14,5

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

Každé číslo jsem rozdělil na 100, 10000 a 1000000 a zkusil to znovu

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)

Zatím je vše dobré !!! Nyní pro uloženou proceduru.

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)

Takže moje orignální dvě čísla fungují dobře. Rozdělme je 100 a zkuste to znovu.

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)

Počkejte, ztratili jsme určitou přesnost. Co se stalo ??? Jak se to stalo ??? Musíte pojmout více desetinných míst (> 2)

AKTUALIZACE 2011-07-25 17:37 EDT

V uložené proceduře jsem nahradil (7,2) (10,7) a vrátil jsem se do správné přesnosti

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 toho, co vidím, vaše uložená procedura pouze opakuje řádky - nikde „neuloží data“ a vy jste okomentovali select:

- SELECT first_float, second_float;

Ano, dostáváte upozornění, když jsou pole float(10,3) převedena na decimal(10,3). Zda jde o problém nebo ne, záleží na tom, co chcete s poli dělat.

Je to jen ukázka skutečného kódu? Možná budete muset přidat další ...