2010-01-17 43 views
2

我需要找出sqlite數據庫的主鍵。從字符串中提取數據的最有效方式

給予相同的字符串:使用PHP

CREATE TABLE casting(movieid INTEGER, actorid INTEGER, PRIMARY KEY (movieid, actorid)) 

什麼會得到一個主鍵陣列的最有效的方法是:

CREATE TABLE cia (name PRIMARY KEY, population INTEGER) 

或?

+2

我不知道您的具體情況的最有效的方法(這可能是一個正則表達式),但是如果你有機會到現場數據庫,最清晰的方式將做一個'SHOW KEYS FROM casting' – 2010-01-17 20:55:17

+1

要添加到Pekka的評論:如果你有權訪問任何數據庫,你可以創建一個臨時表並用SHOW KEYS(我推測)來查詢它。因此:用CREATE TEMPORARY TABLE ...替換CREATE TABLE ...(至少在MySQL中),執行查詢,然後用Pekka的建議查詢表。我應該工作,我相信。 – 2010-01-17 21:02:45

+0

在MySQL上對它進行了測試,並且正如預期的那樣,這確實有效。 – 2010-01-17 21:06:49

回答

1

「我需要找到一個SQLite數據庫的主鍵。」 - 如果可以使用數據庫,則可以避免解析sql字符串:
PRAGMA TABLE_INFO()的結果有一個字段pk,如果字段是表的PRIMARY鍵的一部分,則該字段設置爲1。

$pdo = new PDO('sqlite::memory:'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$pdo->exec('CREATE TABLE cia (name PRIMARY KEY, population INTEGER)'); 
$pdo->exec('CREATE TABLE casting(movieid INTEGER, actorid INTEGER, PRIMARY KEY (movieid, actorid))'); 

showPrimary($pdo, 'cia'); 
showPrimary($pdo, 'casting'); 

function showPrimary($pdo, $tablename) { 
    // only an example. I don't care about injections here 
    echo "primary key for '$tablename'\n"; 
    foreach($pdo->query("PRAGMA TABLE_INFO($tablename)", PDO::FETCH_ASSOC) as $row) { 
    if ($row['pk']) { 
     printf(" %s %s PRIMARY\n", $row['name'], $row['type']); 
    } 
    } 
} 

打印

primary key for 'cia' 
    name PRIMARY 
primary key for 'casting' 
    movieid INTEGER PRIMARY 
    actorid INTEGER PRIMARY 
+0

謝謝,這就是我一直在尋找的 – jcuenod 2010-03-08 14:02:00

1

像這樣的東西應該這樣做:

<?php 
$db = new SQLiteDatabase('dbfilename')) 
$q = @$db->query('SHOW KEYS FROM cia WHERE Key_name = "PRIMARY"'); 
$result = $q->fetch(); 
var_dump(sqlite_fetch_array($result, SQLITE_BOTH)) 
?> 

更新:如果不支持SHOW KEYS,然後你就可以用SELECT statments的infomration和一些工作。這裏被定義爲提供所有表的索引信息你所能PHP函數想:

/** 
* return the list of field in $table 
* @param string $table name of the sql table to work on 
* @param bool $extended_info if true will return the result of a show field query in a query_to_array fashion 
*       (indexed by fieldname instead of int if false) 
* @return array 
*/ 
function list_table_fields($table,$extended_info=FALSE){ 
# Try the simple method 
if((! $extended_info) && $res = $this->query_to_array("SELECT * FROM $table LIMIT 0,1")){ 
    return array_keys($res[0]); 
}else{ # There 's no row in this table so we try an alternate method or we want extended infos    
    if(! $fields = $this->query_to_array("SELECT sql FROM sqlite_master WHERE type='table' AND name ='$table'")) 
    return FALSE; 
    # get fields from the create query 
    $flds_str = $fields[0]['sql']; 
    $flds_str = substr($flds_str,strpos($flds_str,'(')); 
    $type = "((?:[a-z]+)\s*(?:\(\s*\d+\s*(?:,\s*\d+\s*)?\))?)?\s*"; 
    $default = '(?:DEFAULT\s+((["\']).*?(?<!\\\\)\\4|[^\s,]+))?\s*'; 
    if(preg_match_all('/(\w+)\s+'.$type.$default.'[^,]*(,|\))/i',$flds_str,$m,PREG_SET_ORDER)){ 
    $key = "PRIMARY|UNIQUE|CHECK"; 
    $null = 'NOT\s*NULL'; 
    $Extra = 'AUTOINCREMENT'; 
    $default = 'DEFAULT\s+((["\'])(.*?)(?<!\\\\)\\2|\S+)'; 
    foreach($m as $v){ 
     list($field,$name,$type,$default) = $v; 
     # print_r($field); 
     if(!$extended_info){ 
     $res[] = $name; 
     continue; 
     } 
     $res[$name] = array('Field'=>$name,'Type'=>$type,'Null'=>'YES','Key'=>'','Default'=>$default,'Extra'=>''); 
     if(preg_match("!($key)!i",$field,$n)) 
     $res[$name]['Key'] = $n[1]; 
     if(preg_match("!($Extra)!i",$field,$n)) 
     $res[$name]['Extra'] = $n[1]; 
     if(preg_match('!(NO)T\s+NULL!i',$field,$n)) 
     $res[$name]['Null'] = $n[1]; 
    } 
    return $res; 
    } 
    return FALSE; 
} 
} 

Source

相關問題