存储过程会从活动表到历史表中移动太多记录

时间:2014-07-09 04:40:10

标签: mysql powershell

我制作了一个程序,将库存信息从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语句。

1 个答案:

答案 0 :(得分:0)

您的活动表仅保留最后一条记录,因为您在循环中多次调用存储过程,因此每次将所有当前存在的记录(包括在上一次迭代中添加的记录)移动到历史记录表中。你是的,你应该将你的存储过程拆分为两个:一个用于将现有记录移动到历史表(在启动循环之前只调用一次),另一个用于将新记录添加到活动表(在内部调用循环)。

至于能够回滚操作:您需要将语句封装在事务中:

...
$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()
}