2014-07-09 20 views
0

我製作了一個從PowerShell腳本輸入庫存信息到數據庫的過程。存儲過程將太多記錄從活動表移動到歷史記錄表

除了一件事以外,一切都在順利執行。無論何時運行腳本,然後從第一個表中刪除較早的條目,以便它只有通過PowerShell腳本進行的最新值掃描條目,我需要將這些值從一個表中複製到另一個歷史記錄表。但是當我執行它時,只有最後一個條目出現在第一個表中,剩下的所有條目都會發送回歷史表。這是一個邏輯錯誤。

您能否糾正我,以便在我運行腳本時,所有條目都出現在第一個表中,並且只有從我上次運行腳本的時間條目轉到另一個表中?還是我需要爲它創建一個新的過程,在PowerShell循環執行之前我只運行一次?

存儲過程:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `e_inv`.`insertvalue` $$ 
CREATE PROCEDURE "insertvalue"(
    IN assetname_in varchar(255), 
    IN attributename_in varchar(255), 
    IN entry_in varchar(255), 
    IN val_in int, 
    IN sc varchar(255), 
    IN ip varchar(255) 
) 
BEGIN 

DECLARE temp_id INT; 
DECLARE temp_u_id INT; 

INSERT INTO attribute_value_history 
SELECT * FROM attribute_value; 

DELETE FROM attribute_value; 

SELECT u.u_id INTO temp_u_id 
FROM user_system_map u 
WHERE u.ip_add=ip; 

SELECT a.map_id INTO temp_id 
FROM asset_attribute_map a 
INNER JOIN asset_master b ON a.asset_id=b.asset_id 
INNER JOIN attribute_master c ON a.attribute_id=c.attribute_id 
WHERE b.asset_name=assetname_in 
    AND c.attribute_name=attributename_in; 

INSERT INTO attribute_value (
    map_id, 
    entry, 
    u_id, 
    value_id, 
    scan_time 
) VALUES (
    temp_id, 
    entry_in, 
    temp_u_id, 
    val_in, 
    cast(sc as datetime) 
); 
END $$ 

DELIMITER ; 

PowerShell代碼:

cls 
$MySQLAdminUserName = 'root' 
$MySQLAdminPassword = 'root' 
$MySQLDatabase = 'e_inv' 
$MySQLHost = 'egovpc3' 
$ConnectionString = "server=" + $MySQLHost + ";port=3306;uid=" + 
        $MySQLAdminUserName+ + ";pwd=" + $MySQLAdminPassword + 
        ";database="+$MySQLDatabase 

[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data") 
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection 
$Connection.ConnectionString = $ConnectionString 
$Connection.Open() 

$SqlCommand = New-Object MySql.Data.MySqlClient.MySqlCommand 

$arr=get-content -path "D:\Powershell\New Folder\a.txt" 
foreach($comp in $arr) { 
    $ip=([System.Net.Dns]::GetHostAddresses($comp) |select $_.ToString) 

    $count=0 
    $bios=gwmi Win32_UserAccount -computername $comp -authentication packetprivacy 
    # $date = Get-Date -format "yyyy-MM-dd HH:MM:ss" 
    # $date 
    foreach($obj in $bios) { 
    $count=$count+1 
    $Manufacturer=$obj.Manufacturer 
    $Name=$obj.Name 
    #$ReleaseDate=$obj.ConvertToDateTime($obj.ReleaseDate) 
    #$SerialNumber=$obj.SerialNumber 
    #$Version=$obj.Version   
    $date = Get-Date -format "yyyy-MM-dd HH:mm:ss" 

    $date 

    $SqlCommand.CommandText = 
     "call insertvalue('UserAccount','Name','$Name','$count','$date','$ip')" 
    $SqlCommand.Connection = $Connection 

    $SqlCommand.ExecuteNonQuery() 
    } 
} 

編輯:我也想知道如何部署ROLLBACK聲明在此過程中,如果出現任何錯誤和歷史沒有保存。

回答

0

您的活動表只保留最後一條記錄,因爲您在循環中多次調用存儲過程,以便每次將所有當前存在的記錄(包括前一次迭代中添加的記錄)都移動到歷史記錄表中。 Ergo是的,你應該將存儲過程拆分爲兩部分:一部分用於將現有記錄移到歷史表(在啓動循環之前調用一次),另一部分用於將新記錄添加到活動表中循環)。

至於能夠回滾操作:您需要封裝的語句在事務:

... 
$Connection.Open() 

$IsolationLevel = [System.Data.IsolationLevel]::ReadCommitted 
$Transaction = $Connection.BeginTransaction($IsolationLevel) 

$SqlCommand = New-Object MySql.Data.MySqlClient.MySqlCommand 
$SqlCommand.Connection = $Connection 
$SqlCommand.Transaction = $Transaction 
... 
$SqlCommand.CommandText = "..." 
$SqlCommand.ExecuteNonQuery() 
... 
$Transaction.Commit() 
... 

要回滾事務使用$Transaction.Rollback()代替$Transaction.Commit(),例如在異常處理程序中:

$ErrorActionPreference = "Stop" 
try { 
    $Transaction = $Connection.BeginTransaction($IsolationLevel) 
    ... 
    $Transaction.Commit() 
} catch { 
    $Transaction.Rollback() 
}