sql >> データベース >  >> RDS >> Mysql

名前付きプレースホルダーを使用すると、PHP/SQLの挿入エラーが発生します

    $userData ステートメントによってバインドされたプレースホルダーがまったく同じである必要があります。それ以上でもそれ以下でもありません。 PDOStatement::executeを参照してください ドキュメント 、「指定された値より多くの値をバインドすることはできません」という部分。

    execute()への引数を準備する必要があります バインドに正確に一致します。これはarray_intersect_key()で簡単です アレイを正しく配置した場合。私は通常、これを以下のようにプレフィックスも処理する関数でラップします。

    // Adds a prefix to a name for a named bind placeholder
    function prefix($name) {
        return ':'.$name;
    }
    
    // like 'prefix()', but for array keys
    function prefix_keys($assoc) {
        // prefix STRING keys
        // Numeric keys not included
        $newassoc = array();
        foreach ($assoc as $k=>$v) {
            if (is_string($k)) {
                $newassoc[prefix($k)] = $v;
            }
        }
        return $newassoc;
    }
    
    // given a map of datakeyname=>columnname, and a table name, returns an
    // sql insert string with named bind placeholder parameters.
    function makeInsertStmt($tablename, $namemap) {
        $binds = array_map('prefix', array_keys($namemap));
        return 'INSERT INTO '.$tablename.' ('.implode(',',$namemap).') VALUES ('
        .implode(',',$binds).')';
    }
    
    // returns an array formatted for an `execute()`
    function makeBindData($data, $namemap) {
        // $data assoc array, $namemap name->column mapping
        return prefix_keys(array_intersect_key($data, $namemap));
    }
    
    // example to demonstrate how these pieces fit together
    function RunTestInsert(PDO $pdo, $userData) {
        $tablename = 'UserDetails';
        // map "key in $userData" => "column name"
        // do not include ':' prefix in $userData
        $namemap = array(
          'firstName'       => "FirstName",
          'lastName'        => "LastName",
          'address'         => "Address",
          'city'            => "City",
          'county'          => "County",
          'postCode'        => "PostCode",
          'phone'           => "Phone",
          'mobile'          => "Mobile",
          'sex'             => "Sex",
          'DOB'             => "DOB",
          'fundraisingAim'  => "FundraisingAim",
          'weeksAim'        => "WeeksAim",
          'lengthsAim'      => "LengthsAim",
          'hearAbout'       => "HearAboutID",
          'motivation'      => "MotivationID",
          'welcomePackPref' => "WelcomePackID",
          'contactPref'     => "ContactPrefID",
          'title'           => "TitleID",
        );
        $sql = makeInsertStmt($tablename, $namemap);
        $binddata = makeBindData($userData, $namemap);
    
        $pstmt = $pdo->prepare($sql);
        $pstmt->execute($binddata);
    }
    

    このような抽象化の利点は、バインドパラメータ自体について心配する必要がないことです。



    1. SQLServerの単一データベースのデフォルトの日時形式を変更する

    2. 内部結合を使用したPostgreSQLの削除

    3. JPAを介して行をランダムに選択

    4. mysqli(データベース)接続を閉じる必要があるのはいつですか?