2012年8月27日 星期一

[筆記] SQL語法裡問號的功用


今天在寫程式的時候意外的看到一段SQL

    SELECT token FROM oauth_tokens WHERE userID = ? LIMIT 1

而其中的問號引起了我的注意,因為沒有看到userID在程式中出現,所以就查了一下SQL中問號的功用,後來在stackover裡面的這篇好到答案,才發現他其實是一個好習慣,所以就順便筆記下來了

問號的功能,是用來變數化SQL查詢

他一種安全的作法用來取代原來的寫法

    ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = 7")
    result = cmd.Execute()

這個寫法在thingB為固定值的時候沒有什麼問題,但是當你需要動態載入變數的時候,他就會需要寫成這樣(底下的方法是不建議的)

    string s = getStudentName()
    cmd.CommandText = "SELECT * FROM students WHERE (name = '" + s + "')"
    cmd.Execute()

我們就很直覺的使用字串串接的方式來將變數整合成一句SQL,但是這樣會面臨SQL injection的危險,因為當你要寫入的變數,是來自於你不信任的第三方(不論是使用者、或者是hacker)都有可能串接到無法預期的文字,好一點只是SQL statement Error,但是如果對方傳入設計過的字串,例如Robert'); DROP TABLE students; --,則結果會...

    SELECT* FROM students WHERE (name = Robert');
    DROP TABLE students;

就悲劇了,當然你可能會覺得他怎麼知道你的TABLE Name那又是另外一回事了.XD

所以

應該改用這種方式,除了程式有比較好的可讀性以外,還可以事先過濾使用者輸入的字串

    ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = ?")
    cmd.Parameters.Add(7)
    result = cmd.Execute()

當然你也可以使用php PDO的方式來寫入

    $query = 'SELECT token FROM oauth_tokens WHERE userID = ? LIMIT 1';
    $stmt = $this->pdo->prepare($query);
    $stmt->execute(array($this->userID));

都是一種好習慣也是一種好方法:D

沒有留言:

張貼留言