0

ユーザーが情報更新オプションを選択するための複数の簡単な入力があるページがあります。ユーザーはまだ更新プロファイルを定義していない可能性があるため、「INSERT INTO ... ON DUPLICATE KEY UPDATE」ステートメントを使用しようとしています。また、SQL インジェクションの問題を回避するために、sprintf でこれを実行しようとしています。私の問題は、SQL ステートメントのコーディング方法を理解できないことです。これがコードの関連部分です。

$updateSQL = sprintf("INSERT INTO reminders_cfg 
                    (id, day_of, day_of_advance, day_prior, default_time, week_prior, 2_week_prior, 3_week_prior, 4_week_prior, 5_week_prior, day_after, 2_week_after, 50_day_after) 
                    VALUES %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
                    ON DUPLICATE KEY UPDATE ",
                   GetSQLValueString($jeweler, "text"),
                   GetSQLValueString($_POST['DayOf'], "text"),
                   GetSQLValueString($_POST['Advance'], "text"),
                   GetSQLValueString($_POST['DayPrior'], "text"),
                   GetSQLValueString($_POST['Time'], "text"),
                   GetSQLValueString($_POST['WeekPrior'], "text"),
                   GetSQLValueString($_POST['2WeeksPrior'], "text"),
                   GetSQLValueString($_POST['3WeeksPrior'], "text"),
                   GetSQLValueString($_POST['4WeeksPrior'], "text"),
                   GetSQLValueString($_POST['5WeeksPrior'], "text"),
                   GetSQLValueString($_POST['DayAfter'], "text"),
                   GetSQLValueString($_POST['2WeeksAfter'], "text"),
                   GetSQLValueString($_POST['50DaysAfter'], "text"));

これは、Dreamweaver で作成された PHP ページにあります。これが GetSQLValueString 関数の出番です。実際の「ON DUPLICATE KEY UPDATE」部分の後で、すべての変数とプレースホルダーを再度複製する必要がないようにするにはどうすればよいかわかりません。それが理にかなっていることを願っています。

更新:わかりました。これはまだ機能していない私の最新の試みです。

if ((isset($_POST["MM_update"])) && ($_POST["MM_update"] == "form1")) {
    $stmt = $mysqli->prepare("INSERT INTO reminders_cfg 
                    (id, day_of, day_of_advance, day_prior, default_time, week_prior, 2_week_prior, 3_week_prior, 4_week_prior, 5_week_prior, day_after, 2_week_after, 50_day_after) 
                    VALUES :id, :day_of, :day_of_advance, :day_prior, :default_time, :week_prior, :2_week_prior, :3_week_prior, :4_week_prior, :5_week_prior, :day_after, :2_week_after, :50_day_after
                    ON DUPLICATE KEY UPDATE day_of = :day_of, day_of_advance = :day_of_advance, day_prior = :day_prior, default_time = :default_time, week_prior = :Week_prior, 2_week_prior = :2_week_prior, 3_week_prior = :3_week_prior, 4_week_prior = :4_week_prior, 5_week_prior = :5_week_prior, day_after = :day_after, 2_week_after = :2_week_after, 50_day_after = :50_day_after")
                    or die($mysqli->error);
    $stmt->bindParam(':id', $jeweler, PDO::PARAM_INT);      
    $stmt->bindParam(':day_of', $_POST['DayOf'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':day_of_advance', $_POST['Advance'], PDO::PARAM_INT);
    $stmt->bindParam(':day_prior', $_POST['DayPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':default_time', $_POST['Time'], PDO::PARAM_STR, 9);
    $stmt->bindParam(':week_prior', $_POST['WeekPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':2_week_prior', $_POST['2WeeksPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':3_week_prior', $_POST['3WeeksPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':4_week_prior', $_POST['4WeeksPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':5_week_prior', $_POST['5WeeksPrior'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':day_after', $_POST['DayAfter'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':2_week_after', $_POST['2WeeksAfter'], PDO::PARAM_STR, 6);
    $stmt->bindParam(':50_day_after', $_POST['50DaysAfter'], PDO::PARAM_STR, 6);

    $stmt->execute() or die("Insert query error: " . mysql_error());
    $stmt->close(); 
}

これは SQL 構文エラーを生成しています。私はこの 'INSERT INTO ... ON DUPLICATE KEY UPDATE' に慣れていないので、少し行き詰まっています。これがエラーです...

SQL 構文にエラーがあります。使用する正しい構文については、MySQL サーバーのバージョンに対応するマニュアルを確認してください。

4

2 に答える 2

1

ON DUPLICATE KEY UPDATE更新したい値を入力した後、そのままにしておくべき値をそのままにしておきます。例えば

純粋な mysql の例

insert into my_table(name, lastSeen, salary)
              values("Some Name", now(), 25334)
on duplicate key update salary = 25334, lastSeen = now()

nameこの例のprimary keyためだけに、同じ名前のレコードがデータベースに既に存在すると仮定すると、給与とlastSeenを変更することにより、エントリが更新されます。そうでない場合、エントリは指定された値で作成されます。声明の最初の部分で

insert into my_table(name, lastSeen, salary) values("Some Name", now(), 25334)

それが役立つことを願っています。

補足 重複したキーで更新したいフィールドを質問に追加していただければ、コードを使用して質問に答えることができます。

編集 わかりました、これはこれまでで最高の形式のコードではないことを知っていますが、これは役立つでしょうか? (そこに構文エラーがあるかもしれませんが、これが必要な場合は、おそらくアイデアが得られます)

 $updateSQL = sprintf("INSERT INTO reminders_cfg 
                (id, day_of, day_of_advance, day_prior, default_time, 
                 week_prior, 2_week_prior, 3_week_prior, 4_week_prior,
                 5_week_prior, day_after, 2_week_after, 50_day_after) 
                VALUES %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
                ON DUPLICATE KEY UPDATE id = %s, day_of = %s, day_of_advance = %s, 
                     day_prior = %s, default_time = %s, week_prior = %s,
                     2_week_prior = %s, 3_week_prior = %s, 4_week_prior = %s,
                     5_week_prior = %s, day_after = %s, 2_week_after = %s, 
                     50_day_after = %s ",
               GetSQLValueString($jeweler, "text"),
               GetSQLValueString($_POST['DayOf'], "text"),
               GetSQLValueString($_POST['Advance'], "text"),
               GetSQLValueString($_POST['DayPrior'], "text"),
               GetSQLValueString($_POST['Time'], "text"),
               GetSQLValueString($_POST['WeekPrior'], "text"),
               GetSQLValueString($_POST['2WeeksPrior'], "text"),
               GetSQLValueString($_POST['3WeeksPrior'], "text"),
               GetSQLValueString($_POST['4WeeksPrior'], "text"),
               GetSQLValueString($_POST['5WeeksPrior'], "text"),
               GetSQLValueString($_POST['DayAfter'], "text"),
               GetSQLValueString($_POST['2WeeksAfter'], "text"),
               GetSQLValueString($_POST['50DaysAfter'], "text"),
               GetSQLValueString($jeweler, "text"),
               GetSQLValueString($_POST['DayOf'], "text"),
               GetSQLValueString($_POST['Advance'], "text"),
               GetSQLValueString($_POST['DayPrior'], "text"),
               GetSQLValueString($_POST['Time'], "text"),
               GetSQLValueString($_POST['WeekPrior'], "text"),
               GetSQLValueString($_POST['2WeeksPrior'], "text"),
               GetSQLValueString($_POST['3WeeksPrior'], "text"),
               GetSQLValueString($_POST['4WeeksPrior'], "text"),
               GetSQLValueString($_POST['5WeeksPrior'], "text"),
               GetSQLValueString($_POST['DayAfter'], "text"),
               GetSQLValueString($_POST['2WeeksAfter'], "text"),
               GetSQLValueString($_POST['50DaysAfter'], "text"));
于 2013-01-09T04:21:52.883 に答える
-1

ON DUPLICATE KEY UPDATE衝突する可能性のあるキーが 1 つある場合にのみ使用してください。この場合、IDだと思います。

トリガーを定義する方がよい場合があります。このようなもの:

CREATE TRIGGER `reminders_cfg_duplicates` BEFORE INSERT ON `reminders_cfg` FOR EACH ROW
  DELETE FROM `reminders_cfg` WHERE `id`=new.`id`;

たとえば、phpMyAdmin のコントロール パネルから、これを 1 回実行します。その後、データベースは重複の原因となった行を自動的に削除し、更新ですべての値を複製することなく新しい行を挿入できるようにします。

于 2013-01-09T04:16:32.927 に答える