2013-10-24 43 views
0

的Windows XP專業版 的ActiveState Perl的5.14.4 M $ Access 2010中從Access 2010 ACCDB格式分貝

訪問MSysObjects我在其中包含存儲查詢的數量 ACCDB格式的Access數據庫。我想用Perl將它們提取到平面文件。

查詢名稱出現在[MSysObjects]。[Name]中,而查詢 本身似乎以某種方式存儲在MSysQueries中。

但我的問題是在上游 - 我無法讀取這些表中的任何一個。 我已經確認,當我直接打開數據庫的用戶名是「管理員」。

谷歌搜索變成了http://t1134.codeinpro.us/q/5080f5c04f1eba38a4d1547b, 這也解釋了「管理」沒有SELECT權限MSysObjects所以我需要 執行DDL語句GRANT SELECT ON MSysObjects管理員

更多谷歌搜索輪番上漲http://www.connectionstrings.com/access-2010,其中說: 啓用GRANT等特定管理語句我需要添加 Uid = Admin; PWD =; ExtendedAnsiSQL = 1; 我的連接字符串

而且同一頁面有一個Blurb的具體狀態,其中工作組文件是 位於 SystemDB = C:在連接字符串中\ mydatabase.mdw 。 更多相關內容。

所以我有這個

#! /home/gnu/bin/perl 
# 

package main; 

use strict; 
use autouse 'Data::Dumper' => qw(Dumper); 
use DBI; 
use DBD::ODBC; # works for both access and sql server 
use Win32::ODBC; 
use OLE; 
use Win32::OLE; 

# prototypes 
sub _setUpDatabaseHandle_Access_Local_EnableAdminStatements($); 
sub setPermissionsOnTables($); 
sub readTableMSysObjects($); 

#globals 
my $debug = 1; 

my $targetDbFile = undef; 
my $dbh_C = undef; 

print "version of DBD::ODBC is ".$DBD::ODBC::VERSION."\n"; 
print "version of Win32::ODBC is ".$Win32::ODBC::VERSION."\n"; 
print "version of Win32::OLE is ".$Win32::OLE::VERSION."\n"; 

$targetDbFile = "C:/putyer/msaccessdb/here.accdb"; 

$dbh_C = _setUpDatabaseHandle_Access_Local_EnableAdminStatements($targetDbFile); 

setPermissionsOnTables($dbh_C); 
readTableMSysObjects($dbh_C); 

$dbh_C->disconnect() if(defined($dbh_C)); 

exit(0); 
#------------------------------- 
# when you use perl to open an .accdb Access database the Uid is always Admin 
# But user Admin doesn't have SELECT permission on MSysObjects by default you must first 
# grant the permission on the object for the user 
# to enable certain admin commands like CREATE USER, GRANT, REVOKE, DEFAULTS when using CREATE TABLEs 
sub _setUpDatabaseHandle_Access_Local_EnableAdminStatements($) 
{ 
    my ($dbFile) = @_; 

    my $errorHit = 0; 

    my $conn_str = "DBI:ODBC:DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};dbq=".$dbFile; 
    $conn_str .= "; Uid=Admin; Pwd=; ExtendedAnsiSQL=1"; 

    my $dbh = DBI->connect($conn_str); 
    if(!defined($dbh)) { 
    print "db connection failed - ".$DBI::errstr."\n"; 
    $errorHit = 1; 
    } 

    print "connection _setUpDatabaseHandle_Access_Local_EnableAdminStatements failed\n" if($errorHit); 

    return $dbh; 
} 
#------------------------------- 
sub setPermissionsOnTables($) 
{ 
    my ($dbh) = @_; 

    print "entering setPermissionsOnTables\n" if $debug; 

    my $errorHit = 0; 

    my $q = undef; 
    my $sth = undef; 

    unless($errorHit) { 
    $q = "GRANT SELECT ON MSysObjects TO Admin"; 
    $sth = $dbh->prepare($q); 
    if(!defined($sth)) { 
     print "sth failed to define - ".$DBI::errstr."\n"; 
     $errorHit = 1; 
    } else { 
     $sth->execute();      # <=== FAILS HERE 
     if(my $errorMsg = $dbh->errstr) { 
     print "select statement failed - ".$errorMsg."\n"; 
     $errorHit = 1; 
     } 
    } 
    } 

    unless($errorHit) { 
    $q = "GRANT SELECT ON MSysQueries TO Admin"; 
    $sth = $dbh->prepare($q); 
    if(!defined($sth)) { 
     print "sth failed to define - ".$DBI::errstr."\n"; 
     $errorHit = 1; 
    } else { 
     $sth->execute(); 
     if(my $errorMsg = $dbh->errstr) { 
     print "select statement failed - ".$errorMsg."\n"; 
     $errorHit = 1; 
     } 
    } 
    } 

    print "exiting setPermissionsOnTables with errorHit=".$errorHit."\n" if $debug; 
    return $errorHit; 
} 
#------------------------------- 
sub readTableMSysObjects($) 
{ 
    my ($dbh) = @_; 

    print "entering readTableMSysObjects\n" if $debug; 

    my $errorHit = 0; 

    my $q = undef; 
    my $sth = undef; 

    unless($errorHit) { 
    $q = "SELECT * FROM MSysObjects"; # remember that db nulls come over as perl undefs 
    $sth = $dbh->prepare($q); 
    if(!defined($sth)) { 
     print "sth failed to define - ".$DBI::errstr."\n"; 
     $errorHit = 1; 
    } else { 
     $sth->execute(); 
     if(my $errorMsg = $dbh->errstr) { 
     print "select statement failed - ".$errorMsg."\n"; 
     $errorHit = 1; 
     } else { 
     if($sth->rows == 0) { 
      print "select statement returned 0 rows\n"; 
      $errorHit = 1; 
     } else { 
      my $row_hashref = undef; 
      while($row_hashref = $sth->fetchrow_hashref()) { 
      print Dumper($row_hashref); 
      } 
     } 
     } 
     $sth->finish(); 
    } 
    } 

    print "exiting readTableMSysObjects\n" if $debug; 
    return $errorHit; 
} 

試圖與臭名昭著 執行第一GRANT無法打開Microsoft Access數據庫引擎工作組信息文件 消息時失敗。

所以看來我也需要這個文件,我似乎無法在我的盒子上找到這個文件。 或者可以/我應該使用不同的連接?像其中之一?

#------------------------------- 
sub _setUpDatabaseHandle_Access_Local_ADO_ACE($) 
{ 
    my ($dbFile) = @_; 

    my $errorHit = 0; 

    my $conn_str = "DBI:ADO:Provider=Microsoft.ACE.OLEDB.12.0;Data Source=".$dbFile; 
    $conn_str .= "; Persist Security Info=False"; 
# print $conn_str."\n"; 

    my $dbh = DBI->connect($conn_str); 
    if(!defined($dbh)) { 
    _pushErrorMsg("db connection failed - ".$DBI::errstr); 
    $errorHit = 1; 
    } 

    print "connection _setUpDatabaseHandle_Access_Local_ACE failed\n" if($errorHit); 

    return $dbh; 
} 
#------------------------------- 
sub _setUpDatabaseHandle_Access_Local_ADO($) 
{ 
    my ($dbFile) = @_; 

    my $errorHit = 0; 

    my $conn_str = "DBI:ADO:File Name=".$dbFile; 

    my $username = undef; 
    my $password = undef; 

    my $dbh = DBI->connect($conn_str, $username, $password); 
    if(!defined($dbh)) { 
    _pushErrorMsg("db connection failed - ".$DBI::errstr); 
    $errorHit = 1; 
    } 

    print "connection _setUpDatabaseHandle_Access_Local_ADO failed\n" if($errorHit); 

    return $dbh; 
} 

任何指針/提示/建設性的批評,尤其是例子都歡迎。

TIA,

還是學習史蒂夫

回答

1

我的經驗是,Jet數據庫引擎和相關的驅動程序似乎有機會獲得[... MSys的]表中的ADO鎖定非常緊密, OleDb的。他們似乎仍然可以通過DAO訪問,但是如果您使用的是DAO,那麼您並不需要大驚小怪[MSysObjects],因爲您只需遍歷QueryDefs集合即可。

以下VBScript將每個查詢的SQL代碼轉儲到單獨的文本文件中。您既可以通過

  • 代碼移植到Perl的(和使用任何機制(S),可在Perl來操縱COM對象),它集成到您​​的Perl項目,或
  • 從你的Perl腳本炮擊和運行VBScript本身(通過cscript.exe)。
Option Explicit 
Dim dbe ' As DAO.DBEngine 
Dim db ' As DAO.Database 
Dim qdf ' As DAO.QueryDef 
Dim fso ' As FileSystemObject 
Dim f ' As TextStream 

Set fso = CreateObject("Scripting.FileSystemObject") ' New FileSystemObject 
Set dbe = CreateObject("DAO.DBEngine.120") ' New DAO.DBEngine 
Set db = dbe.OpenDatabase("C:\__tmp\main.accdb") 
For Each qdf In db.QueryDefs 
    Set f = fso.CreateTextFile("C:\__tmp\" & qdf.Name & ".sql") 
    f.WriteLine qdf.SQL 
    f.Close 
    Set f = Nothing 
Next 
db.Close 
Set db = Nothing 
Set dbe = Nothing 
Set fso = Nothing 
+0

感謝您的回覆和示例!我會在第二天左右嘗試一下。 – user1201168

相關問題