簡體   English   中英

創建一個 MySQL 存儲過程來更新記錄

[英]Creating a MySQL stored procedure to update records

我正在轉換所有現有的 MSSQL 數據庫,並且存儲過程卡在一個新的存儲過程中,我需要更新現有記錄。 一旦將記錄插入數據庫並成功發送電子郵件(或至少傳遞到 SMTP 服務器),就會從 Web 表單調用該過程

我在 MSSQL 中有一個工作程序很長一段時間了,但我正在嘗試將其轉換為 MySQL。 我傳入了 3 個變量 - 一點表示電子郵件已發送,一個字符串表示已使用哪個 SMTP 服務器發送電子郵件和一個唯一的記錄 ID,以便我知道要更新的記錄。 我還將日期和時間添加到另一個字段以了解程序何時運行。

我有以下內容,但不斷收到錯誤消息“#1064 - 您的 SQL 語法有錯誤;請檢查與您的 MySQL 服務器版本相對應的手冊,以獲取在第 7 行附近使用的正確語法 - 但我沒有在第 7 行看不到任何東西 - 至少在我看來。

我嘗試使用的代碼是:

CREATE PROCEDURE `sp_Test`(
  `emailSent_In` BIGINT UNSIGNED,
  `emailTransport_In` VARCHAR(100),
  `formSecret_In` VARCHAR(32)
)
BEGIN
  SET @`query` := CONCAT('UPDATE ',`tbl_JustSayThanks`,' 
  SET `emailSent` = `emailSent_In`,
  `emailTransport` = ',`emailTransport_In`,',
`emailSentDate` = NOW()
    WHERE `formSecret` = ', `formSecret_In`, '');
  PREPARE `stmt` FROM @`query`;
  EXECUTE `stmt`;
       @`query` := NULL;
  DEALLOCATE PREPARE `stmt`;
END//
DELIMITER ;

僅供參考,我正在使用基於我從 wchiquito 收到的先前答案的 CONCAT,最終將傳入表名。 但是,在去那里之前,我想讓它在簡化的級別上工作。

以下是錯誤的:

SET @`query` := CONCAT('UPDATE ',`tbl_JustSayThanks`,' 

因為您似乎將 SQL 文本與tbl_JustSayThanks連接tbl_JustSayThanks ,但我認為您的意思是使用標識符本身。 因此,這應該是:

SET @`query` := CONCAT('UPDATE `tbl_JustSayThanks`', 

以下是錯誤的:

`emailTransport` = ',`emailTransport_In`,',

因為該變量是一個 VARCHAR,但您沒有在 SQL 語句中將其作為字符串文字引用。 很容易與多個級別的引用混淆。 應該是:

`emailTransport` = ''', `emailTransport_In`, ''',

出於同樣的原因,以下是錯誤的:

WHERE `formSecret` = ', `formSecret_In`, '');

應該是:

WHERE `formSecret` = ''', `formSecret_In`, '''');

這仍然會遇到 SQL 注入問題,除非您可以保證輸入參數是安全的(這不是一個好的假設)。 如果需要將值連接到 SQL 表達式中,則應使用QUOTE()函數進行轉義:

SET @query = CONCAT('
  UPDATE tbl_JustSayThanks 
  SET emailSent = ', QUOTE(emailSent_In), '
      emailTransport = ', QUOTE(emailTransport_In), '
      emailSentDate = NOW()
  WHERE formSecret = ', QUOTE(formSecret_In));

更多評論:

  • 您不需要用反引號分隔每個標識符,只需要那些與 SQL 保留字沖突或包含空格或標點符號或國際字符的標識符。 您顯示的所有標識符都不需要分隔。
  • 當您使用准備好的語句時,您應該使用帶有? 占位符,而不是將變量連接到 SQL 字符串中。 您不要在 SQL 查詢中引用參數占位符。 這樣您就不會遇到像您發現的那樣難以調試的語法錯誤。

這是一個顯示修復程序的示例:

CREATE PROCEDURE sp_Test(
  emailSent_In BIGINT UNSIGNED,
  emailTransport_In VARCHAR(100),
  formSecret_In VARCHAR(32)
)
BEGIN
  SET @query = '
    UPDATE tbl_JustSayThanks
    SET emailSent = ?,
        emailTransport = ?,
        emailSentDate = NOW()
    WHERE formSecret = ?';
  SET @es = emailSent_In;
  SET @et = emailTransport_In;
  SET @fs = formSecret_In;
  PREPARE stmt FROM @query;
  EXECUTE stmt USING @es, @et, @fs;
  DEALLOCATE PREPARE stmt;
END//
DELIMITER ;

最后評論:

  • 您的示例查詢沒有動態語法元素,只有動態 所以你根本不需要使用准備好的語句。

這就是我真正編寫程序的方式:

CREATE PROCEDURE sp_Test(
  emailSent_In BIGINT UNSIGNED,
  emailTransport_In VARCHAR(100),
  formSecret_In VARCHAR(32)
)
BEGIN
  UPDATE tbl_JustSayThanks
  SET emailSent = emailSent_In,
      emailTransport = emailTransport_In,
      emailSentDate = NOW()
  WHERE formSecret = formSecret_In;
END//
DELIMITER ;

您還應該知道 MySQL 存儲過程遠不如 Microsoft SQL Server。 MySQL 不保留已編譯的存儲過程,它不支持包,它沒有調試器...我建議您不要使用 MySQL 存儲過程。 請改用應用程序代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM