简体   繁体   中英

Why does this command work in SQL Server Management Studio but not from PowerShell

I have the following SQL command which reads the index fragmentation of my database called Logik :

USE Logik

SELECT 
    OBJECT_NAME(ind.OBJECT_ID) AS TableName,
    ind.name AS IndexName, indexstats.index_type_desc AS IndexType,
    indexstats.avg_fragmentation_in_percent
FROM 
    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats
INNER JOIN 
    sys.indexes ind ON ind.object_id = indexstats.object_id
                    AND ind.index_id = indexstats.index_id
WHERE 
    indexstats.avg_fragmentation_in_percent > 0

In SQL Server Management Studio, this works without a problem and returns the tables with their fragementation.

Yesterday, this also worked from PowerShell. I didn't change any code but today it doesn't work anymore. Does anyone have an idea why?

$Data will stay empty:

param(
    [string]$connectionstring = "Server=some\instance;uid=sa;pwd=dfdfdfdf;Database=Logik;Integrated Security=False;MultipleActiveResultSets=True;Connection Timeout=900;"
)

# Stop bei Fehler
$ErrorActionPreference = "SilentlyContinue"
$database = "logik"

# Database Connection herstellen
$con = New-Object System.Data.SqlClient.SqlConnection
$con.ConnectionString = $connectionstring
Try { $con.Open() } 
Catch { Throw $_.Exception.Message }

# command einlesen um Fragmentation zu lesen
$command = "
USE Logik
SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName,
ind.name AS IndexName, indexstats.index_type_desc AS IndexType,
indexstats.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats
INNER JOIN sys.indexes ind 
ON ind.object_id = indexstats.object_id
AND ind.index_id = indexstats.index_id
WHERE indexstats.avg_fragmentation_in_percent > 0"

# Command Zusammensetzen
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.CommandText = $command
$cmd.Connection = $con
$cmd.CommandTimeout = 2000

# Execute Command
Try { $result = $cmd.ExecuteReader() }
Catch { Throw $_.Exception.Message }

# Output von Resultat
$Data = New-Object System.Data.DataTable
$Data.load($result)

The whole thing is strange because, after I load the data, I put it into another variable $tables , and I want to throw when $tables is empty.

I use this code to check if there is any data loaded, and it returns an empty row for $tables , but $tables.count returns 8. how is that possible?

# Logik Tabellen
$tables = $Data | ? { $_.avg_fragmentation_in_percent -ge 5 -and $_.IndexName -ne 0 }
if (!$tables) { Throw "Keine Datenbank gefunden, oder keine Höher als 5% Fragmentation" }
$tables.count ; $tables ; pause

USE shouldn't be used at all. It's a batch command understood by SSMS or sqlcmd, not a T-SQL command.

In this case, the connection string connects to the Logik database already. There's no reason to use USE to switch to it.

Just use :

$command = "
SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName,
ind.name AS IndexName, indexstats.index_type_desc AS IndexType,
...

If you want to use tables from different databases in the same query, use a three-part name, eg: MyDatabase.dbo.ThatTableName .

You should probably not use the ADO.NET library inside a Powershell script. Powershell won't complain if you misspell a variable name, it will create a new empty one.

Use the SQL Server Powershell provider instead. This way you can write the following code :

Import-Module Sqlps -DisableNameChecking;
cd SQL\MyRemoteServer\DEFAULT\Databases\MyDatabase
$result=Invoke-SqlCmd -Query "SELECT @@VERSION;"

The $result variable will hold the results of the query after that.

If the query returns multile rows, or even a single one with multiple fields, you'll get back an array of objects with properties that match the columns.

The following query :

$tables=Invoke-SqlCmd -Query "SELECT * from sys.tables"

Will return the contents of the sys.tables table. You can access individual columns as properties. This script will return all table names :

$tables | %{ $_.name;}

Chained together :

Invoke-SqlCmd -Query "SELECT * from sys.tables" | % {$_.name}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM