16

price (int) と price_display (varchar) の 2 つの列を持つテーブルがあります。

price は実際の価格です。例: "9990"

price_display は、「$9.99」や「9.99Fr」などの視覚的表現です。

正規表現を介して 2 つの列が一致することを確認できました。

price_display は正規表現形式ではありません (price/1000, 2)

しかし、不一致の場合は、price_display 列から値を抽出し、price 列に設定する必要があります。これらはすべて update ステートメントのコンテキスト内で行います。私は方法を理解することができませんでした。

ありがとう。

4

6 に答える 6

37

この関数は、文字列から 0 ~ 9 の数字のみを返すジョブを実行します。これは、使用しているプレフィックスまたはポストフィックスに関係なく、問題を解決するためにうまく機能します。

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#815

参照用にここにコピー:

SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
  DECLARE i, len SMALLINT DEFAULT 1;
  DECLARE ret CHAR(32) DEFAULT '';
  DECLARE c CHAR(1);

  IF str IS NULL
  THEN 
    RETURN "";
  END IF;

  SET len = CHAR_LENGTH( str );
  REPEAT
    BEGIN
      SET c = MID( str, i, 1 );
      IF c BETWEEN '0' AND '9' THEN 
        SET ret=CONCAT(ret,c);
      END IF;
      SET i = i + 1;
    END;
  UNTIL i > len END REPEAT;
  RETURN ret;
END |
DELIMITER ;

SELECT digits('$10.00Fr'); 
#returns 1000
于 2009-06-13T23:46:54.603 に答える
5

1 つのアプローチは、REPLACE()関数を使用することです。

UPDATE my_table
SET    price = replace(replace(replace(price_display,'Fr',''),'$',''),'.','')
WHERE  price_display not regexp format(price/1000, 2);

これは、あなたが与えたサンプルデータに対して機能します:

'$9.99'
'9.99Fr'

私のテストでは、どちらも999という結果になりました。このような更新では、最初にデータベースを確実にバックアップし、アイテムの形式を認識することが重要です。次のクエリを実行すると、すべての「悪者」を確認できます。

SELECT   DISTINCT price_display
FROM     my_table
WHERE    price_display not regexp format(price/1000, 2)
ORDER BY price_display;
于 2009-06-10T21:24:04.160 に答える
1

文字列から最後の番号を返します:

CREATE FUNCTION getLastNumber(str VARCHAR(255)) RETURNS INT(11)
DELIMETER //
BEGIN
    DECLARE last_number, str_length, position INT(11) DEFAULT 0;
    DECLARE temp_char VARCHAR(1);
    DECLARE temp_char_before VARCHAR(1);


IF str IS NULL THEN
    RETURN -1;
END IF;

SET str_length = LENGTH(str);

WHILE position <= str_length DO
    SET temp_char = MID(str, position, 1);

    IF position > 0 THEN
        SET temp_char_before = MID(str, position - 1, 1);
    END IF;

    IF temp_char BETWEEN '0' AND '9' THEN
        SET last_number = last_number * 10 + temp_char;
    END IF;
    IF (temp_char_before NOT BETWEEN '0' AND '9') AND 
           (temp_char BETWEEN '0' AND '9') THEN                 
        SET last_number = temp_char;
    END IF;

    SET position = position + 1;
END WHILE;

RETURN last_number;
END//
DELIMETER;

次に、この関数を呼び出します。

select getLastNumber("ssss111www222w"); 印刷する 222

select getLastNumber("ssss111www222www3332"); 印刷 3332

于 2016-10-23T17:43:39.527 に答える
1

文字列の最初の数字を検出してこれを返すプロシージャを作成し、そうでない場合は 0 を返します。

    DROP FUNCTION IF EXISTS extractNumber;
    DELIMITER //
    CREATE FUNCTION extractNumber (string1 VARCHAR(255)) RETURNS INT(11) 
        BEGIN
        DECLARE position, result, longitude INT(11) DEFAULT 0;
        DECLARE string2 VARCHAR(255);
        SET longitude = LENGTH(string1);
        SET result = CONVERT(string1, SIGNED);
        IF result = 0 THEN
            IF string1 REGEXP('[0-9]') THEN
                SET position = 2;
                checkString:WHILE position <= longitude DO
                    SET string2 = SUBSTR(string1 FROM position);
                    IF CONVERT(string2, SIGNED) != 0 THEN
                        SET result = CONVERT(string2, SIGNED);
                        LEAVE checkString;
                    END IF;
                    SET position = position + 1;
                END WHILE;
           END IF;
        END IF;
        RETURN result;
    END //
    DELIMITER ;
于 2013-08-20T17:27:18.003 に答える
1

これは「コーディングの恐怖」です。リレーショナル データベース スキーマをこのように記述してはなりません。

データを検証するために複雑で不要なコードを書かなければならない。

次のようなことを試してください:

SELECT CONCAT('$',(price/1000)) AS Price FROM ...

さらに、整数の代わりにfloatdoubleまたはを使用できます。real

通貨データを保存する必要がある場合は、通貨フィールドを追加するか、システム ロケール関数を使用して正しい形式で表示することを検討してください。

于 2009-06-10T21:20:11.157 に答える