it-swarm.com.de

Daten für Spalte abgeschnitten

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

In dieser MySQL-Abfrage führe ich diese Art von Operation in einer gespeicherten Prozedur aus, aber die Linux-Umgebung phpmyadmin gibt die folgende Warnung aus:

Hinweis: # 1265 Daten für Spalte 'float_one' in Zeile 5 abgeschnitten

Hat jemand eine Idee, wie ich dieses Problem lösen kann?

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

und das Verfahren

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 ;

und das Ergebnis

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

Was ist der Wert von float_one zum Zeitpunkt der Konvertierung ???

Beachten Sie dieses Beispiel aus MySQL 5.5.12 unter 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)

Möglicherweise wurden Daten abgeschnitten, wenn sich in float_one eine Zahl größer als 99999.99 befand. Vielleicht hat mysql float_one und float_two einzeln in DECIMAL (7,2) konvertiert, bevor die Division durchgeführt wurde. Versuchen Sie, DECIMAL (10,2) oder höher zu verwenden, um große Werte aufzunehmen.

UPDATE 2011-07-25 15:05 EDT

Hier gibt es definitiv ein Kürzungsproblem

Gemäß MySQL-Referenzhandbuch Seite 442 Absätze 2,

DECIMAL- und NUMERIC-Werte werden als Zeichenfolgen und nicht als binäre Gleitkommazahlen gespeichert, um die Dezimalgenauigkeit dieser Zahlen zu erhalten. Für jede Ziffer des Wertes wird ein Zeichen verwendet, der Deziamlpunkt (wenn Skala> 0) und das Vorzeichen (für negative Zahlen). Wenn die Skala 0 ist, enthalten die Werte DECIMAL und NUMERIC keinen Dezimalpunkt oder Bruchteil.

Der maximale Bereich von DECIMAL und NUMERIC ist der gleiche wie für DOUBLE, aber der tatsächliche Bereich für die angegebene DECIMAL- oder NUMERIC-Spalte kann durch die Genauigkeit und Skalierung für eine Give-Spalte eingeschränkt werden. Wenn einer solchen Spalte ein Wert mit weiteren Ziffern zugewiesen wird Wenn der Dezimalpunkt von der angegebenen Skala zugelassen wird, wird der Wert auf diese Skala gerundet. Wenn einer DECIMAL- oder NUMERIC-Spalte ein Wert zugewiesen wird, dessen Größe den Bereich überschreitet, der durch die angegebene (oder standardmäßige) Genauigkeit und Skalierung impliziert wird, speichert MySQL den Wert, der den entsprechenden Endpunkt dieses Bereichs darstellt.

Sie müssen eine größere Präzision und/oder Skalierung berücksichtigen.

Hier ist ein Beispiel, warum

Ich habe diese gespeicherte Prozedur unter Verwendung Ihrer Spezifikationen für DECMIAL und NUMERIC geschrieben.

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 ;

Ich habe für diesen Test zwei Werte verwendet: 290,0 und 14,5.

Vor dem Aufruf der gespeicherten Prozedur NumTest habe ich 290.0/14.5 manuell berechnet

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

Ich teilte jede Zahl durch 100, 10000 und 1000000 und versuchte es erneut

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)

So weit, ist es gut !!! Nun zur gespeicherten Prozedur.

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)

Meine ursprünglichen zwei Zahlen funktionieren also einwandfrei. Teilen wir sie durch 100 und versuchen es erneut.

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)

Warten Sie, wir haben etwas Präzision verloren. Was ist passiert ??? Wie ist es passiert ??? Sie müssen mehr Dezimalstellen (> 2) aufnehmen.

UPDATE 2011-07-25 17:37 EDT

Ich habe (7,2) in der gespeicherten Prozedur durch (10,7) ersetzt und die richtige Genauigkeit wiedererlangt

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

Soweit ich sehen kann, durchläuft Ihre gespeicherte Prozedur nur die Zeilen - sie speichert die Daten nirgendwo und Sie haben das select auskommentiert:

- SELECT first_float, second_float;

Ja, Sie erhalten Warnungen, wenn die Felder float(10,3) in decimal(10,3) konvertiert werden. Ob sie ein Problem darstellen oder nicht, hängt davon ab, was Sie mit den Feldern tun möchten.

Ist dies nur ein Beispiel für den realen Code? Möglicherweise müssen Sie weitere ...