【问题标题】:Updating row in datatable and saving to database更新数据表中的行并保存到数据库
【发布时间】:2021-09-16 12:29:56
【问题描述】:

我必须在 MS SQL Server 的表中重置名为“certRenewal”的列。我正在 Powershell 中尝试这个。基本上,我正在考虑的想法是在 DataTable 对象中获取整个表,然后遍历所有行并找到“certRenewal”在哪里 $true (它的位列)。并将其更改为 $false。这是代码。该代码没有给我任何错误,但它也没有更新 SQL Server 中的表。

param(
        [string]$SQLServerName="ServerName\InstanceName"
        ,[string]$SQLDatabaseName="MyDataBase"
        ,[string]$SQLTableName = "UserList"
        ,[string]$SQLQuery1="SELECT * FROM $SQLTableName"
    )
    
    # Create connection
    $sqlConn = New-Object System.Data.SqlClient.SqlConnection
    $sqlConn.ConnectionString = “Server=$SQLServerName;Integrated Security=true;Initial Catalog=$SQLDatabaseName”
    $sqlConn.Open()
    
    
    # Get all users
    $sqlCommand = $sqlConn.CreateCommand()
    $sqlCommand.CommandText = $SQLQuery1
    
    
    $dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $sqlCommand
    $dataTable = New-Object System.Data.DataTable
    $dataAdapter.Fill($dataTable) | Out-Null
    
    
    
    foreach($dataRow in $dataTable.Rows)
    {
        if($dataRow["certRenewal"] -eq $true)
        {
            $dataRow["certRenewal"] = $false
            $dataTable.AcceptChanges()
        }
    }
    
    
    $dataAdapter.Update($dataTable)
    $sqlConn.Close()

我知道我也可以构建和发送更新命令,我不需要 DataAdapter。但我想知道是否通过 DataTable 并通过迭代所有行并更新行并将其保存为 DataTable,是否可以这样做?

【问题讨论】:

    标签: powershell datatable sqldataadapter


    【解决方案1】:

    你能用 DataTable 做你描述的事情吗?绝对可以。但是为什么,考虑到您的要求,这似乎是一种过度杀伤力。总之……

    你的问题是find where "certRenewal" is $true - 但你的代码是if($dataRow["certRenewal"] -eq $false) - 我猜这是一个错字?我认为您的问题出在这条线上,但由于 SQL 中的数据类型没有像您对 PowerShells $true/$false 的预期那样评估。

    删除一些Write-Host 行来确认执行流程,如下所示:

            Write-Host $dataRow["certRenewal"]
            if($dataRow["certRenewal"] -eq $false)
            {
                Write-Host "certRenewal is false"            ​
               ​$dataRow["certRenewal"] = $true
               ​$dataTable.AcceptChanges()
           ​}else{
               ​Write-Host "certRenewal is true"
           ​}
    

    从 POSH 运行 SQL 命令:DESCRIBE $SQLTableName; 或检查 Management Studio 中的表以找到 certRenewal 的确切数据类型。 (或者你可以在你的 foreach 中包含$dataRow| ConvertTo-Json 来查看数据)。它可能是 bitchar(1) 类型 - 位只是数字,字符需要用引号括起来 'Y'


    大锤敲碎坚果...

    使用 DataTable 进行这样一个简单的操作是不必要且昂贵的 - 而且您不会从这笔费用中获得太多价值。在实际层面上,随着行数的增加,这种方法的低效率将成为一个问题。

    作为一项规则,您应该根据需要选择尽可能少的数据,因此SELECT * FROM $SQLTableName 不是一个好的开始(如果您处理数百或数千行,这可能没问题,但这是一个坏习惯,并且不会规模好)。 (以下假设 certRenewal 是位数据类型,您需要将这些示例调整为您的表架构)。

    SELECT * FROM $SQLTableName WHERE certRenewal = 0 会稍有改进 - 所以你只选择 certRenewal 为假的行 - 但这仍然会拉动所有其他从未使用过的列...

    进一步的改进是只选择您打算使用的列:SELECT certRenewal FROM $SQLTableName WHERE certRenewal = 0 - 这大大减少了原始查询的数据总量。您只需为代码所期望的每一行获取一个值。

    通常,您希望避免不必要的数据库往返,并尽可能少地来回发送数据 - 它更快、更便宜,这真是个好主意。所以,除了select * 语句 - 我会使用 SQL UPDATE 命令。

    UPDATE 语句将更新与 where 子句匹配的所有行,并将字段设置为给定值。这意味着传输的数据最少 - 仅返回修改的行数等,所有工作都由数据库服务器完成。

    以下命令将指示 SQL 查找所有 certRenewal 为 false 的行,并将它们设置为 true。如果将此查询与select * 方法进行比较,即使在行数较少的情况下,速度差异也应该是可见的。带宽需要花钱,而数据传输需要时间 - 尽可能尝试将操作卸载到 SQL,如果您必须获取数据,请尽可能少地获取。

    UPDATE $SQLTableName
    SET certRenewal = 0
    WHERE certRenewal = 1;
    

    另外,我认为您不需要 $dataTable.AcceptChanges() - 它只是将行标记为已更新,实际上并没有做任何有用的事情,您只需要在循环之后提交更改即可

    【讨论】:

    • 嗨@MisterSmith。感谢您的答复。是的,数据类型是位(不是布尔,对不起,我的错)。是的,这个条件是一个错字。应该是找到“certRenewal”是$true 的地方。我想做一个 Foreach 循环的原因是因为我必须向用户发送电子邮件通知,并且该表中的其他列包含用户的电子邮件。现在我还没有到那一步,所以我的代码没有反映任何关于电子邮件的内容。但基本上如果 certRenewal -eq 为真,那么 1. 发送电子邮件用户和 2. 将 certrenewal 更改为 $False。但是使用这种方法它不会更新 certRenewal 列。 :(
    • 这是有道理的。编辑您的问题并添加您的最新代码并包含 Write-Host 行的输出。如果仍然建议将您的 sql 更改为 select ID,Name,Email from $SQLTableName where certRenewal = 1 之类的东西(或任何您的字段名称 - 确保在上面的示例中包含一个唯一键“ID”,以便在您拨打 UPDATE 时使用)。我希望将 if($dataRow["certRenewal"] -eq $true) 更改为 if($dataRow["certRenewal"] -eq 1) 如果该字段有点应该工作。 $true/$false 是 powershell 构造而不是 SQL。
    • 我有一些新要求。我会再次发布我的问题。这次我会放表格def和示例数据等。感谢您对这个问题的耐心和您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 2016-02-24
    • 2018-06-01
    相关资源
    最近更新 更多