この質問について何かが私を悩ませています...なぜ各行のinsert_idが必要なのですか? 設定テーブルに挿入している場合、設定をユーザーに関連付けるには、何らかのユーザーキーをテーブルに追加する方がよいように思えます。私はおそらく全体像を見ていないだけかもしれませんが、これは私が得ている考えです:
+---------------------------------------+
| `settings` |
+------+--------+-----------+-----------+
| id | user | setting | value |
+------+--------+-----------+-----------+
| `id` INT(11) PRIMARY AUTO_INCREMENT |
+---------------------------------------+
| `user` INT(11) |
+---------------------------------------+
| `setting` VARCHAR(15) |
+---------------------------------------+
| `value` VARCHAR(25) |
+---------------------------------------+
+---------------------------------------+
| `users` |
+------+--------+--------+--------------+
| id | name | email | etc |
+------+--------+--------+--------------+
| `id` INT(11) PRIMARY AUTO_INCREMENT |
+---------------------------------------+
| `name` VARCHAR(32) |
+---------------------------------------+
| `email` VARCHAR(64) |
+---------------------------------------+
| `etc` VARCHAR(64) |
+---------------------------------------+
ここでの私の基本的な考え方は、insert_id(s) で行っていることは、ユーザーと設定の間の参照を作成しようとする方法であり、誰が何を設定したかを知り、後で設定を返すことです。
要点を完全に失った場合は、トピックに戻ってください。別の解決策を考え出そうとしますが、あなたが行こうとしている場所の近くにいる場合:
実際に insert_id(s) を使用して 2 つのテーブルを関連付けようとしている場合は、以下のコードのようなものは意味がありません (上記のようなテーブル構造があると仮定します)。
users
$user は特定のユーザー ( . id
)への参照であると仮定します。
また、データベースに入れようとしている $settings という連想配列があると仮定します。
$mysqli = new mysqli('host', 'username', 'password', 'database') or trigger_error('[MYSQLI]: Could not connect.');
if ($mysqli)
{
foreach ($settings AS $setting_name=>$setting_value)
{
// I'll do individual queries here so error checking between is easy, but you could join them into a single query string and use a $mysqli->multi_query();
// I'll give two examples of how to make the multi_query string below.
$sql = "INSERT INTO `settings` (`id`, `user`, `setting`, `value`) VALUES ('', $user, '$setting_name', '$setting_value')";
$mysqli->query($sql) or trigger_error('[MYSQLI]: ' . $mysqli->error . '['.$sql.']';
}
$mysqli->close() // Since we know in this scope that $mysqli was created we need to close it when we are finished with it.
}
ユーザーの設定が必要な場合は、JOIN を使用して SELECT を実行して、すべての設定とユーザー情報をまとめることができます。設定テーブルに複数のエントリがあり、users テーブルに 1 つのエントリがあるため、何か特別なことをする必要があるかどうかはわかりませんが、これを台無しにすれば、誰かが私たちの両方をまっすぐに設定できると確信しています。
$mysqli = new mysqli('host', 'username', 'password', 'database') or trigger_error('[MYSQLI]: Unable to connect.');
if ($mysqli)
{
$sql = "SELECT `users`.`name`, `users`.`email`, `users`.`id`, `users`.`etc`, `settings`.`setting`, `settings`.`value` FROM `settings` JOIN (`users`) ON (`users`.`id`=`settings`.`user`) WHERE `settings`.`user`=$user GROUP BY `settings`.`user` ORDER BY `settings`.`user` ASC";
if ($result=$mysqli->query($sql))
{
if ($result->num_rows == 0)
echo "Uh oh! $user has no settings or doesn't exist!";
else
{
// Not sure if my sql would get multiple results or if it would get it all in one row like I want so I'll assume multiple which will work either way.
while ($row=$result->fetch_array())
print_r($row); // Just print the array of settings to see that it worked.
}
$result->free(); // We are done with our results so we release it back into the wild.
} else trigger_error('[MYSQLI]: '.$mysqli->error . '['.$sql.']');
$mysqli->close(); // Our if ($mysqli) tells us that in this scope $mysqli exists, so we need to close it since we are finished.
}
前に述べたように、私は決して mysql(i) の専門家ではなく、おそらく物事を合理化する方法があり、JOIN ステートメントの構文でいくつかの間違いを犯したか、GROUP BY のような余分な句を使用しただけかもしれません。 . 設定をユーザーに結合すると、ユーザーと、WHERE 句に一致する設定からのすべての可能な値を含む単一の結果が得られるかどうかわからなかったため、SELECT をプルしsettings
て結合しました。users
私は、それぞれに 1 つの結果があった場所にしか参加A
したことがありませんB
が、JOIN が適切な一般的な領域にあると確信しています。
複数のクエリの代わりに、multi_query に対して単一のクエリ文字列を作成する例を挙げると言いました。
$arr = array();
foreach($settings AS $setting_name=>$setting_value)
{
$arr[] = "INSERT INTO `settings` (`id`, `user`, `setting`, `value`) VALUES ('', $user, '$setting_name', '$setting_value')";
}
$sql = join('; ', $arr);
また
foreach($settings AS $setting_name=>$setting_value)
{
$sql = ( isset($sql) ) ? $sql.'; '."INSERT INTO `settings` (`id`, `user`, `setting`, `value`) VALUES ('', $user, '$setting_name', '$setting_value')" : "INSERT INTO `settings` (`id`, `user`, `setting`, `value`) VALUES ('', $user, '$setting_name', '$setting_value')";
}
最後に注意しておきたいのは、ユーザーに対して同じ設定の複数のエントリが特に必要でない限り、INSERT クエリの前に UPDATE を実行し、結果が $mysqli->insert_id == 0 の場合にのみ INSERT を実行することです。ユーザーの設定変更の履歴を保持しようとしていて、そのために複数のエントリが必要な場合は、次のようなテーブル構造を含むログを含む別のテーブルを作成することをお勧めします。
+--------------------------------------------------+
| `logs` |
+------+--------+--------+-----------+-------------+
| id | time | user | setting | new_value |
+------+--------+--------+-----------+-------------+
| `id` INT(11) PRIMARY AUTO_INCREMENT |
+--------------------------------------------------+
| `time` TIMESTAMP |
+--------------------------------------------------+
| `user` INT(11) |
+--------------------------------------------------+
| `setting` INT(11) |
+--------------------------------------------------+
| `new_value` VARCHAR(25) |
+--------------------------------------------------+
CURRENT_TIMESTAMPのデフォルトを作成するtime
か、日付 ('Ymd G:i:s') をそのフィールドに挿入するだけの場合、新しい設定が作成または変更されたときにログに挿入することで、設定の変更を追跡できます。
UPDATE で何も変更されなかった場合に INSERTS を実行するには、2 つの別個のステートメントを使用できます。「INSERT VALUES() ON DUPLICATE KEY UPDATE ...」でも可能ですが、複数の UNIQUE フィールドを持つテーブルでは、この方法は明らかに推奨されません。後者の方法を使用すると、単一のクエリを意味しますが、user
とsetting
UNIQUE (または DISTINCT?) の組み合わせを作成する必要があります。UNIQUEを作成した場合、私が間違っていない限り、テーブルには ='foo'setting
を 1 つしか持つことができません。setting
2 つのステートメントでそれを行うには、次のようにします。
$sql = "UPDATE `settings` SET `value`='bar' WHERE `user`=$user AND `setting`='foo' LIMIT 1";
$mysqli->query() or trigger_error('[MYSQLI]: ' . $mysqli->error . '['.$sql.']');
if ( $mysqli->affected_rows == 0 )
{
$sql = "INSERT INTO `settings` (`id`, `user`, `setting`, `value`) VALUES ('', $user, 'foo', 'bar')";
$mysqli->query($sql) or trigger_error('[MYSQLI]: ' . $mysqli->error . '['.$sql.']');
}
上記のコードでは、必要に応じて $mysqli->insert_id を $mysqli->affected_rows に置き換えることができますが、最終結果は同じです。INSERT ステートメントは、UPDATE がテーブル内で何も変更しなかった場合にのみ呼び出されます (これは、その設定とそのユーザーのレコードがなかったことを示します)。
これが非常に長い返信であり、元の質問から逸脱していることをお詫びしますが、それがあなたの真の目的/目標に関連していることを願っています. 真の SQL マスターからの、私の SQL ステートメントを改善する方法についてのあなたの応答とコメントを楽しみにしています。