[英]PHP and MySQL - REPLACE INTO if NULL on a specific column
我試圖使用REPLACE INTO來更改列的值,除非它為NULL。
這是代碼的一部分:
// Set query
$this->db->query('REPLACE INTO sessions VALUES (:id, :access, :data, :identifier)');
// Bind data
$this->db->bind(':id', $id);
$this->db->bind(':access', $access);
$this->db->bind(':data', $data);
$this->db->bind(':identifier', $rnd_id);
它是PDO的一部分,因此我將沿途綁定變量以幫助防止SQL注入。
我只想在列為NULL時才替換“標識符”,但是我不確定SQL查詢應該是什么。
編輯
僅提供更多信息。 上面的當前代碼用於創建一個會話表,其中包含會話ID,上次訪問會話的時間,會話數據和唯一標識符。 該標識符最終將用於客戶端cookie。
執行查詢后,會話行將更新。 ID保持不變,訪問權限和數據已更新。 我需要一種更新id / access / data的方法,但是僅當標識符為null時才更新。
上面的代碼基於本教程: http : //culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/
我正在嘗試適應。
這是我到目前為止所擁有的一切:
database.class.php
這提供了PDO連接和功能
<?php
class Database{
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASSWORD;
private $dbname = DB_NAME;
private $stmt;
private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
}
}
public function query($query){
$this->stmt = $this->dbh->prepare($query);
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute(){
return $this->stmt->execute();
}
public function resultset(){
$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function single(){
$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function rowCount(){
return $this->stmt->rowCount();
}
public function lastInsertId(){
return $this->dbh->lastInsertId();
}
public function beginTransaction(){
return $this->dbh->beginTransaction();
}
public function endTransaction(){
return $this->dbh->commit();
}
public function cancelTransaction(){
return $this->dbh->rollBack();
}
public function close(){
return $this->dbh=NULL;
}
}
?>
session.php
該代碼取代了PHP默認的會話處理,並將數據保存到具有ID(會話ID),訪問(上次訪問時間)和數據(會話數據)列的會話表中。
include_once('database.class.php');
class Session {
/**
* Db Object
*/
private $db;
public function __construct(){
// Instantiate new Database object
$this->db = new Database;
// Set handler to overide SESSION
session_set_save_handler(
array($this, "_open"),
array($this, "_close"),
array($this, "_read"),
array($this, "_write"),
array($this, "_destroy"),
array($this, "_gc")
);
// Start the session
session_start();
}
/**
* Open
*/
public function _open(){
// If successful
if($this->db){
// Return True
return true;
}
// Return False
return false;
}
/**
* Close
*/
public function _close(){
// Close the database connection
// If successful
if($this->db->close()){
// Return True
return true;
}
// Return False
return false;
}
/**
* Read
*/
public function _read($id){
// Set query
$this->db->query('SELECT data FROM sessions WHERE id = :id');
// Bind the Id
$this->db->bind(':id', $id);
// Attempt execution
// If successful
if($this->db->execute()){
// Save returned row
$row = $this->db->single();
// Return the data
return $row['data'];
}else{
// Return an empty string
return '';
}
}
/**
* Write
*/
public function _write($id, $data){
//set the random id length
$random_id_length = 10;
//generate a random id encrypt it and store it in $rnd_id
$rnd_id = crypt(uniqid(rand(),1));
//to remove any slashes that might have come
$rnd_id = strip_tags(stripslashes($rnd_id));
//Removing any . or / and reversing the string
$rnd_id = str_replace(".","",$rnd_id);
$rnd_id = strrev(str_replace("/","",$rnd_id));
//finally I take the first 10 characters from the $rnd_id
$rnd_id = substr($rnd_id,0,$random_id_length);
// Create time stamp
$access = time();
// Set query
$this->db->query('REPLACE INTO sessions VALUES (:id, :access, :data, :identifier)');
// Bind data
$this->db->bind(':id', $id);
$this->db->bind(':access', $access);
$this->db->bind(':data', $data);
$this->db->bind(':identifier', $rnd_id);
// Attempt Execution
// If successful
if($this->db->execute()){
// Return True
return true;
}
// Return False
return false;
}
/**
* Destroy
*/
public function _destroy($id){
// Set query
$this->db->query('DELETE FROM sessions WHERE id = :id');
// Bind data
$this->db->bind(':id', $id);
// Attempt execution
// If successful
if($this->db->execute()){
// Return True
return true;
}
// Return False
return false;
}
/**
* Garbage Collection
*/
public function _gc($max){
// Calculate what is to be deemed old
$old = time() - $max;
// Set query
$this->db->query('DELETE * FROM sessions WHERE access < :old');
// Bind data
$this->db->bind(':old', $old);
// Attempt execution
if($this->db->execute()){
// Return True
return true;
}
// Return False
return false;
}
}
?>
我在表中添加了新列“標識符”。 我還向_write
函數添加了$rnd_id
。 這將生成一個10個字符的唯一標識符。
當查詢$this->db->query('REPLACE INTO sessions VALUES (:id, :access, :data, :identifier)');
第一次運行時,我可以在數據庫中看到新行,所有4列均按預期填充。 問題出在隨后的執行中-盡管:id保持不變,但標識符會使用新的10個字符代碼進行更新。 我想防止這種情況的發生,並且只在第一次添加代碼。 隨后的執行應保留標識符不變,或將其替換為相同的值。
您是否正在嘗試做這樣的事情?
UPDATE sessions
set id = :id,
access = :access,
data = :data,
identifier = :identifier
where identifier is null and id = :id;
編輯:
我認為您想要的是on duplicate key update
:
insert into sessions(id, access, data, identifier)
select :id, :access, :data, :identifier
on duplicate key update access = :access, data = :data;
您需要確保id
是主鍵或唯一鍵。 您可以這樣做:
create unique index idx_sessions_id on sessions(id);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.