簡體   English   中英

SQLSTATE [42000]:語法錯誤或訪問沖突:1064

[英]SQLSTATE[42000]: Syntax error or access violation: 1064

我正在寫一些軟件。 讀者的摘要版本:用戶選擇一個軟件包,輸入他們的姓名,電子郵件和所需的子域。 然后檢查子域,看是否有人已經注冊了它,以及它是否僅為字母數字。 我已經使用OO mysqli完成了所有這些工作,但是我決定轉向PDO。

錯誤的確切措辭:

SQLSTATE [42000]:語法錯誤或訪問沖突:1064 SQL語法有錯誤; 檢查與您的MySQL服務器版本相對應的手冊,以在第1行的'-> subdomain'附近使用正確的語法

當我實例化Admin對象時,一切都很好。 但是,當我調用createAccount()函數時,所有事情都createAccount() 堆棧跟蹤無處不在,我幾乎無法弄清何時開始對此進行故障排除。 我在這里檢查了其他答案,它們似乎都太局限了,因此這里是產生它的代碼,然后是所有包含錯誤的方法。 開始了....

首先,產生錯誤的代碼:

include 'classes/Admin.class.php';
$admin = new Admin('test@test.com');

try {
    $admin->createAccount('John', 'Smith', 'test', 'pro');
}
catch(Exception $e) {
    echo '<pre />';
    echo $e->getMessage();
    die(print_r($e->getTrace()));
}

管理員類構造函數

public function __construct($email) {
        $this->email = $email;

        include 'Database.class.php';
        include 'PasswordHash.php';

        define("DB_HOST", "localhost");
        define("DB_USER", "root");
        define("DB_PASS", "");
        define("DB_NAME", "ems");

        $this->data = new Database;
        $this->hasher = new PasswordHash(8, false);
    }

在Admin類中,檢查子域

private function checkSubdomain() {
    $this->data->query('SELECT * FROM clients WHERE subdomain = :subdomain');
    $this->data->bind(':subdomain', $this->subdomain);
    $this->data->execute();

    return ($this->data->rowCount() == 0) && (ctype_alnum($this->subdomain));
}

PDO類執行,綁定和查詢

public function execute() {
    return $this->stmt->execute();
}

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;
            default:
                $type = PDO::PARAM_STR;
        }
    }
    $this->stmt->bindValue($param, $value, $type);
}

該錯誤在我的代碼中非常普遍,因此我認為它僅在PDO類中有效,但是我的Session類工作得很好。 此外,我的查詢僅使用mysqli即可完美運行,因此我對語法很有信心。 任何幫助是極大的贊賞。

根據要求,創建帳戶功能:

public function createAccount($firstname, $lastname, $subdomain, $package)
{
    $this->firstname = $firstname;
    $this->lastname  = $lastname;
    $this->subdomain = $subdomain;
    $this->package   = $package;
    //does the subdomain exist, or is it invalid?
    if(!$this->checkSubdomain())
        throw new Exception('This domain is not available. It can only contain letters and numbers and must not already be taken.');

    //now comes the table creation, provided everything is in order
    $this->setup();
}

這是createAccount調用的設置函數(沒有所有表結構):

private function setup() {
    $isError = false;
    $queries = array(
        //all of these are CREATE statements, removed for security reasons
        );

    //need a database that matches with the client subdomain
    $this->data->query('CREATE TABLE $this->subdomain');
    $this->data->bind(':subdomain', $this->subdomain);

    //PDO secured...execute
    $this->data->execute();

    $this->data->beginTransaction();
    foreach($queries as $query) {
        $this->data->query($query);
        if(!$this->data->execute()) { //we hit some sort of error, time to GTFO of here
            $isError = true;
            $this->data->cancelTransaction();
            //die('Error with: ' . $query);
            break;
        }
    }

    if(!$isError) {
        $this->data->endTransaction();
        mkdir('a/' . $this->subdomain, 0755);
        $this->generatePass();
        //this is where I insert the user into the admin table using PDO, removed for security
        $this->data->execute();
    }

    $this->data->close();

}

這是導致錯誤的原因:

$this->data->query('CREATE TABLE $this->subdomain');
$this->data->bind(':subdomain', $this->subdomain);

正如Michael Berkowski和Andrewsi在評論中指出的那樣,您不能將值綁定到:subdomain占位符,因為它在查詢中沒有被指出,即使是PDO占位符也只能用於值,而不是數據庫,表名或列名

如果要動態創建這種SQL查詢,則需要將數據庫,表或列名稱括在反引號中 (以防萬一,您的列和名稱包含SQL保留關鍵字可能會破壞查詢),並轉義放置的 ,但是如果已經使用PDO ,則不能使用MySQLi

由於PDO並沒有提供實現此real_escape_string()方法,並且在實踐中並不需要轉義這樣的值(除非您確實擁有名為Ye'name列,這完全是愚蠢的恕我直言),因此使用簡單的過濾器preg_match()preg_replace()足夠好:

if (preg_match('/^[\w_]+$/i', $this->subdomain)) {
    // note the ` (backtick), and using " (double quotes):
    $this->data->query("CREATE TABLE `{$this->subdomain}`"); 
} else {
    // throw exception or error, do not continue with creating table
}

在PHP中僅對" (雙引號)字符串使用' (單引號-撇號)的幾個例子:

$a = 1;
$b = 2;
echo '$a + $b'; // outputs: $a + $b
echo "$a + $b"; // outputs: 1 + 2
$c = array(5, 10);
echo '\$c[0] = {$c[0]}'; // outputs: \$c[0] = {$c[0]}
echo "\$c[0] = {$c[0]}"; // outputs: $c[0] = 5

雙引號字符串內的{}用於數組和對象屬性訪問,可用於常規變量。
$括住雙引號中的\\$否則將假定變量調用。

我遇到了此錯誤,但原因略有不同。 您必須在SELECT語句'SELECT'。$ userfield'中保留空格。 FROM'。$ usertable。 'WHERE 1'效果很好,但是'SELECT'。$ userfield.'FROM'。$ usertable.'WHERE 1'失敗了。

    $stmt = $dbh->query(
    'SELECT ' . $userfield . ' FROM ' . $usertable . ' WHERE 1 '
    );
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

提供信息,以防有人通過42000錯誤代碼查找擊中該條目。

暫無
暫無

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

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