PHP 5.6.11
MySQL 5.6
CentOS 7 (with MySQL 5.6)
注意:這不是我的文字代碼。我抽象了某些部分。執行時沒有錯誤。沒有數據寫入contact
表。PHP:爲什麼我的PDO準備語句不能將數據插入到我的表中?
我有一個名爲通訊錄...
CREATE TABLE IF NOT EXISTS `database`.`contact`(
`contact_id` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Contact ID',
`firstname` VARCHAR(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'First name.',
`lastname` VARCHAR(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Last name.',
`email` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'E-mail address.',
`phone` VARCHAR(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Telephone number',
`country_code` VARCHAR(7) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Country code number',
`extension` VARCHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Telephone extension',
`company` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Company affiliation.',
`address` VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Street Address.',
`city` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'City.',
`state` VARCHAR(6) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'State.',
`zip` VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Zip code.',
`country` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Country.',
`phone_type` ENUM('Cellular', 'Landline') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Telephone type',
`time_to_contact` ENUM('A.M.', 'P.M.') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Morning or Afternoon',
`contact_pref` ENUM('Email', 'Phone', 'Mail') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Contact preference',
`job_location` VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Jobsite location',
`news_subscribed` ENUM('N', 'Y') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Contact subscribed to newsletter.',
`news_subs_token` VARCHAR(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Used when subscribing to the newsletter.',
`news_unsub_token` VARCHAR(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Used when unsubscribing to the newsletter.',
`message_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'Time of last message.',
CONSTRAINT `contactconstr01` PRIMARY KEY (`contact_id`))
ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci COMMENT 'Contacts (external) table.';
...我想用這個存儲過程,嵌入準備好的聲明中,插入記錄。
CREATE DEFINER = 'blahfoobar'@'localhost'
PROCEDURE `database`.add_contact_sp(
IN contact_id VARCHAR(32),
IN firstname VARCHAR(30),
IN lastname VARCHAR(30),
IN email VARCHAR(128),
IN phone VARCHAR(12),
IN country_code VARCHAR(7),
IN extension VARCHAR(5),
IN company VARCHAR(50),
IN address VARCHAR(100),
IN city VARCHAR(50),
IN st VARCHAR(6),
IN zip VARCHAR(10),
IN country VARCHAR(50),
IN phone_type VARCHAR(8),
IN time_to_contact VARCHAR(4),
IN contact_preference VARCHAR(5),
IN job_location VARCHAR(100),
IN news_subscribed VARCHAR(1),
IN news_sub_token VARCHAR(60),
IN news_unsub_token VARCHAR(60))
COMMENT 'Insert new contact record.'
LANGUAGE SQL
DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
BEGIN
SET @id = contact_id;
SET @fName = firstname;
SET @lName = lastname;
SET @eMail = email;
SET @p = phone;
SET @cc = country_code;
SET @ext = extension;
SET @comp = company;
SET @addr = address;
SET @c = city;
SET @s = st;
SET @zCode = zip;
SET @coun = country;
SET @pType = phone_type;
SET @ttc = time_to_contact;
SET @cPref = contact_preference;
SET @jLoc = job_location;
SET @news = news_subscribed;
SET @nSubT = news_subs_tokens;
SET @nUnsubT = news_unsub_token;
PREPARE `insert_contact_stmt` FROM
'INSERT INTO `contact`
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
EXECUTE `insert_contact_stmt` USING @id, @fName, @lName, @eMail, @p, @cc, @ext, @comp, @addr, @c, @s, @zCode, @coun, @pType, @ttc, @cPref, @jLoc, @news, @nSubT, @nUnsubT;
DEALLOCATE PREPARE `insert_contact_stmt`;
END//
安全設置的樣子....
GRANT INSERT ON TABLE `database`.`contact` TO 'blahfoobar'@'localhost';
GRANT SELECT ON TABLE `database`.`contact` TO 'blahfoobar'@'localhost';
GRANT UPDATE ON TABLE `database`.`contact` TO 'blahfoobar'@'localhost';
GRANT DELETE ON TABLE `database`.`contact` TO 'blahfoobar'@'localhost';
GRANT EXECUTE ON PROCEDURE `database`.`add_contact_sp` TO 'blahfoobar'@'localhost', 'blahblahblah'@'localhost';
...其中 'blahblahblah' @ 'localhost' 的代表,使PDO連接期間到MySQL服務器的連接實際用戶階段(未示出)。
我的PHP,子類Contact
(超一流Person
)的保護方法如下所示,其中頂部附近$db
對象是一個PDO連接的包裝對象。
protected function insert()
{
try
{
$this->db->startTransaction();
$stmt = $this->db->prepare('add_contact_sp(:contact_id, :firstname, :lastname, :email, :phone, :country_code, :extension, :company, :address, :city, :state, :zip, :country, :phone_type, :time_to_contact, :contact_pref, :job_location, :news_subscribed, :news_sub_token, :news_unsub_token');
if($stmt instanceof PDOStatement)
{
//Where $stmt is passed by reference.
$this->db->bindParam($stmt, ':contact_id', $this->id);
$this->db->bindParam($stmt, ':firstname', $this->firstname);
$this->db->bindParam($stmt, ':lastname', $this->lastname);
$this->db->bindParam($stmt, ':email', $this->email);
$this->db->bindParam($stmt, ':phone', $this->phone);
$this->db->bindParam($stmt, ':country_code', $this->countryCode);
$this->db->bindParam($stmt, ':extension', $this->extension);
$this->db->bindParam($stmt, ':company', $this->company);
$this->db->bindParam($stmt, ':address', $this->address);
$this->db->bindParam($stmt, ':city', $this->city);
$this->db->bindParam($stmt, ':state', $this->state);
$this->db->bindParam($stmt, ':zip', $this->zip);
$this->db->bindParam($stmt, ':country', $this->country);
$this->db->bindParam($stmt, ':phone_type', $this->phoneType);
$this->db->bindParam($stmt, ':time_to_contact', $this->timeToContact);
$this->db->bindParam($stmt, ':contact_pref', $this->contactPref);
$this->db->bindParam($stmt, ':job_location', $this->jobLocation);
$this->db->bindParam($stmt, ':news_subscribed', $this->newsSubscribed);
$this->db->bindParam($stmt, ':news_sub_token', $this->newsSubToken);
$this->db->bindParam($stmt, ':news_unsub_token', $this->newsUnsubToken);
if(!$stmt->execute())
{
print_r($stmt->errorInfo(), true); //Just for debugging.
}
else
{
$this->db->commit();
}
}
else
{
throw new PDOException("Failed to prepare the PDO statement.");
}
}
catch(Exception $e)
{
$this->db->rollback();
return false;
}
return true;
}
沒有錯誤。沒有數據寫入數據庫。沒有。是否有可能使用嵌入了預準備語句的MySQL存儲過程執行PDO事務?
這是我的數據庫連接選項的要求。
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\' COLLATE \'utf8mb4_unicode_ci\''
];
我建議你看着寫[一個最小的完整的例子(http://stackoverflow.com/help/mcve),並給予明確的問題陳述:你是怎麼想到要發生了什麼事情,而不是。現在,有太多的細節很難找到真正的問題。 – IMSoP
@IMSoP它只是一張桌子。然後,一個存儲過程將記錄插入到該表中。接下來,安全設置。最後,調用存儲過程的PHP。像這樣看,這不是一個複雜的演示。如果你看過一個,你就會看到它們。不過,我沒有得到任何錯誤。奇怪。 – Melinda
@AnonyRutledge您是否認爲嘗試綁定太多參數可能存在問題? – Melinda