0

他に挿入が見つかった場合に行を更新するためのSQL Serverの次のクエリを思いつきました

merge tblpermissions  as t
using (select cid, uid from tblpermissions) as s
on (t.cid = s.cid and t.uid=s.uid)
when not matched
THEN INSERT (cid, uid, [read], [write], [readonly], [modify], [admin]) VALUES ('1',   '1', 1, 1, 0, 1, 1) 
when matched 
THEN UPDATE SET [read]=1, write=1, readonly=0, modify=1, admin=1 ;

エラーは発生しませんが、期待どおりの結果が得られません。テーブルにレコードがなく、新しいレコードを挿入していません。

修正はありますか?

編集:あなたの提案を考慮して、期待される結果なしで、以下のようにさらに変更しました-

MERGE INTO tblpermissions  as t
using (SELECT '1' AS cid, '1' AS uid FROM tblpermissions) as s
on (t.cid = s.cid and t.uid=s.uid)
WHEN NOT MATCHED 
THEN INSERT (cid, uid, [read], [write], [readonly], [modify], [admin])
VALUES  ('1', '1', 1, 1, 0, 1, 1) 
WHEN MATCHED
THEN UPDATE SET [read]=1, write=1, readonly=0, modify=1, admin=1 ;

編集: pls は下部にあるコメントを確認してください。以下は、提案に対する改善されたクエリです。

MERGE INTO tblpermissions  as t
using tblpermissions as s
on (t.cid = s.cid and t.uid=s.uid)
WHEN NOT MATCHED 
THEN INSERT (cid, uid, [read], [write], [readonly], [modify], [admin])
VALUES  ('1', '1', 1, 1, 0, 0, 1) 
WHEN MATCHED
THEN UPDATE SET [read]=1, write=1, readonly=0, modify=1, admin=1 ;

編集: select-if found update-else 代替を下に挿入 -

$query = "SELECT * FROM ".SQL_PREFIX."permissions\n"
              ."WHERE cid='".$cid."' AND uid='".$uid."'";
    $sth = $this->dbh->query($query);
    $res = $sth->fetch();
    //print_r($res);var_dump($res);
    if(!$res || $res==null)
    {
        $query = "INSERT INTO ".SQL_PREFIX."permissions (cid, uid, [read], [write], [readonly], [modify], [admin])\n"
            ."VALUES ('$cid', '$uid', ".implode(", ", $values).")";
        if(!($sth = $this->dbh->query($query)))
            $this->db_error(__('Error inserting user permissions.'),
                $query);
    }else{
        $query = "UPDATE ".SQL_PREFIX."permissions SET ".implode(", ", $sets).";";
        if(!($sth = $this->dbh->query($query)))
            $this->db_error(__('Error updating user permissions.'),
                $query);
    } 

編集:以下は、この状況のmysqlソリューションです-

INSERT into tblpermissions (cid, uid, [read], [write], [readonly], [modify], [admin]) VALUES ('1', '1', 1, 1, 0, 0, 1) ON DUPLICATEキー更新 [読み取り]=1、書き込み=1、読み取り専用=0、変更=1、管理者=1

これは、キーワード DUPLICATE KEY を使用するだけです。また、cid と uid の組み合わせには一意のキー制約があることを再度強調したいと思います。したがって、mysql が行うことは、最初に、挿入しようとしている cid と uid の組み合わせを探すだけで、更新が見つかった場合は新しいレコードを挿入します。

4

1 に答える 1

2

ソース テーブルとターゲット テーブルが同じであるため、行が一致しないことはありません。tblpermissions のすべての行が更新されています。

挿入するには、次の例のように、ソース テーブル ( usingで定義) がターゲット テーブルと異なる必要があります。

merge tblpermissions  as t
using (select cid, uid from otherTable) as s
on (t.cid = s.cid and t.uid = s.uid)

merge tblpermissions  as t
using (select cid, uid from tblpermissions) as s
on (t.cid = s.cid + 1 and t.uid = s.uid + 1)

編集:任意のテーブルからの選択の結果の代わりに定数値を使用しているため、おそらく次のようにします:

merge tblpermissions as t
using (select '1' cid, '1' uid, 1 [read], 1 [write], 0 [readonly], 0 [modify], 1 [admin]) s
on (t.cid = s.cid and t.uid = s.uid)
when matched 
    then update set [read] = s.[read], write = s.[write], readonly = s.[readonly], modify = s.[modify], admin = s.[admin]
when not matched
    then insert (cid, uid, [read], [write], [readonly], [modify], [admin]) values (s.cid, s.uid, s.[read], s.[write], s.[readonly], s.[modify], s.[admin]);

行マージを 1 つだけ挿入するのはやり過ぎだと思いますが、次のようにする方が簡単です。

if exists (select 1 from tblpermissions where cid = '1' and uid = '1')
update tblpermissions set [read] = 1, write = 1, readonly = 0, modify = 1, admin = 1 where cid = '1' and uid = '1'
else
    insert tblpermissions (cid, uid, [read], [write], [readonly], [modify], [admin]) VALUES ('1', '1', 1, 1, 0, 1, 1)

SQL Server には、これを実行するためのより短い、またはより洗練された方法があるとは思いませんon duplicate。MySQL とは異なります。

于 2013-05-09T14:17:55.490 に答える