Powershell working with SQL Server datasets - sql

I was trying to filter the dataset that i got from SQL server database. Here is the scenario...
I'm getting servername,dbname columns from one of the database servers and returning the result set as return ,$dataSet.Tables[0]. I'm getting the results correctly in a table format.
But now i got all the server names to a variable from this dataset as below,
$servers=$dataSet_1.servername | select -unique
Now, i'm trying to loop through each server and get the database list associated to each server as follows, but looks like this is not a right approach as it is getting me all the severs and their database names is every iteration
foreach($server IN $servers)
{
write-host $server
$dataSet_1 | Where-Object {$dataSet_1.servername -eq $server} | select $_.dbname
}
Could someone help me the right approach are a way to do this.
Sample output: (Basically it should iterate each server and display its databasename)
ServerA
dbname
database1
database2
database3
....
ServerB
dbname
database1
database8
database10
....
ServerC
...
Thanks,

"$dataSet_1 | where {$_.servername -eq $server} " is still returning the System.Data.DataTable type.
Does this return the desired output?
$dataSet_1 | where {$_.servername -eq $server} | %{$_.dbname}

Maybe this:
$servers=$dataSet_1.servername | Select-Object -Unique
$filteredSet = $dataSet_1 | Where-Object { $servers -contains $_.servername }
$filteredSet

Related

Powershell - Can I scrape SQL file and compare results?

I am fairly new to Powershell and have run into a bit of a pickle.
I am trying to scrape a SQL script in txt file format. My goal is to check if every created (volatile) table is also dropped in the same file. And if not, output the name of the table which is not dropped in the SQL script.
On top of that I would like check if the "drop" of the table is AFTER "create volatile table" and not BEFORE, because that would be wrong syntax. Do you think it's somehow possible?
I tried to do it by extracting lines of codes where is the create table string, then using regex to get name(string) of the table and saving it to variable. I did the same with the "drop table...". Now I am trying to compared those two (string) variables by converting them to list, object or whatever. I feel like I am in dead end.
$vtMatch = Get-ChildItem "$packagepath\Scripts\" -Recurse | Select-String -Pattern "create multiset volatile table VT_","create multiset volatile table vt_"
$vtMatch = $vtMatch.line
$vt = $vtMatch | Select-String 'vt_(.*?)(?=,)' -AllMatches | Select-Object -Expand matches | ForEach-Object {$_.value}
$dropMatch = Get-ChildItem "$packagepath\Scripts\" -Recurse | Select-String -Pattern "drop table VT_","drop table vt_"
$dropMatch = $dropMatch.line
$drop = $dropMatch | Select-String 'vt_(.*?)(?=;)' -AllMatches | Select-Object -Expand matches | ForEach-Object {$_.value}
$missing = Compare-Object -ReferenceObject $vt -DifferenceObject $drop -Property item
$missing
The variable $vt contains these strings:
vt_R_transaction_Dm
vt_h_bank_account
vt_DD_Agreement_Detail_1
vt_DD_Agreement_Detail_2
vt_DM_Agreement_Detail_Prebase
vt_DM_Agreement_Detail_RWA
vt_DM_Agreement_Detail_1
vt_posted_transaction
vt_DM_Corp_Objective_Specific_MAT
vt_DM_Party_Detail
And variable $drop contains these strings:
vt_DD_Agreement_Detail_1
vt_DD_Agreement_Detail_2
vt_DM_Agreement_Detail_Prebase
vt_DM_Agreement_Detail_RWA
vt_DM_Agreement_Detail_1
vt_DM_Corp_Objective_Specific_MAT
vt_posted_transaction
vt_DM_Party_Detail

Powershell and SQL Strings passed from AD

Okay here is an interesting one. I will try to simplify the issue down
In Powershell, lets say I use the following:
$users = Get-ADUser | Select samAccountName, givenName, sn
Active Directory example has 3 users:
First Name Last Name
__________ _________
Jen Jones
Jason O'Neil
Jake Johnson
I have a SQL Update command within powershell to update a table that looks like so:
ForEach($U in $Users){
$SQLAddInfo = "
UPDATE
Table1
SET
User_Last_Name = '$($User.sn)',
User_First_Name = '$($User.givenName)'
WHERE
User_ID = '$($User.samAccountName)'"
$SqlConnection.Open()
$SqlCmd.CommandText = $SQLaddInfo
$SqlCmd.Connection = $SqlConnection
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
}
Now the problem is that this works most of the time, but when I get to the last name of O'Neil, SQL thinks the apostrophe is a terminator for the SQL command. How do I use variables here and still have Powershell or SQL ignore the apostrophe?
Parameterized queries. Anything else, and O'Neil is far from your only problem.
.... coming back a day later, because I forgot to talk about Table-Valued parameters.
If the Get-ADUser call here produces 1000 results, you're gonna run 1000 SQL queries, and that's not fun. You can do better, by sending all of the data to the server in one step via a table-valued parameter, where you do an INSERT/SELECT that uses that parameter to only run one query.

SQL query over multiple tables in one database

enter code hereI have the following problem:
I have a bunch of Tables in a Vertica Database say:
+------------+
| Tablenames |
+------------+
| a_1 |
| a_2 |
| a_34 |
| b_1 |
| b_4 |
+------------+
The tables are not exactly the same but have mostly similar entries. And now I want to make one query over all tables that start with a_ (a_1 a_2 a_34).
Is there a way to search through all the tables for the string a_ in their name, output some sort of list and than either use a for loop or join operation with the generated list?
Once I get the new table (lets call it temp_table) that has all the table names that start with a_ I would like to run one query over all of them, something like that (Matlab syntax):
for ii=1:length(temp_table)
Data{ii}=SELECT * FROM temp_table(ii) WHERE paste_condition_here
end
So Data should be a new table that appends the new rows with each iteration.
#Nirjihar - there is on information_schema (you need v_catalog), you are confusing with MySQL.
select TABLE_NAME from v_catalog.TABLES where TABLE_NAME like 'a_%';
This will return all tables with a criteria of 'a_%'
Just as a complement !
In Vertica you won`t have loops ! For this you have to use UDP(user defined procedures), this can be written in the language of your choice (shell,java,R,C++).
i will go ahead and post on model here for you :
1 - Shell proc - to be created in the procedures folder
#!/bin/bash
. /home/dbadmin/.profile
/opt/vertica/bin/vsql -U $username -w $password -t -o /tmp/query.sql -c"
SELECT
' select * from '
||TABLE_SCHEMA
||'.'
||TABLE_NAME
||';'
FROM
v_catalog.TABLES where TABLE_NAME like '%$1%'
"
/opt/vertica/bin/vsql -U $username -w $password -F $'|' -At -o /tmp/query_output.csv -f /tmp/query.sql
2 - change sh file privs
chmod 4750 query_table.sh
3 - make sure you have the .profile file populated accordingly
. /home/dbadmin/.profile
#!/bin/bash
username=dbadmin
password=secrectpasswd
export username
export password
Note: this is to avoid passwd in text and only have one point of text passwd
4 - Register the UDP with Vertica Catalog
. /home/dbadmin/.profile
admintools -t install_procedure -f /vertica/catalog//procedures/query_table.sh -d -p $password
5 -Create the UDP inside the database
. /home/dbadmin/.profile
/opt/vertica/bin/vsql -U $username -w $password -c "CREATE PROCEDURE dba.query_table(table_name varchar) AS 'query_table.sh' LANGUAGE 'external' USER 'dbadmin';"
6 - execute the proc
select dba.query_table('you possible table name here');
7 - check results
a - you will get a file with the query
b - one file with the exported data(csv '|' delimited).
i have a similar post here:
http://www.aodba.com/create-vertica-schema-fly/
To get all the tables that start from a_:-
select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME like 'a_%'
Then you can alias this and join the list or each table as you like.

How to change column name if it contains certain characters

How to change the name of table columns using SQL Server.
The Database table looks like this:
| Column 1 | Column 2 | Column 3 | Q115($) | Q215($) | Q315($) | .... | QXYY($)|
Where new columns are added over time in the format "Quarter"+"Year"+"($)"
I want to write a query that does the following in Microsoft SQL Server:
For all columns that contains "($)":
Change Name of Column from QXYY($) to 20YY QX
Changing column names is probably something you want to do manually instead of as a mass change. You can get a list of all the columns in all tables in your DB using the sys.all_columns table so something like
select all_objects.name as Table_nm, all_columns.name as Column_nm
from sys.all_columns
inner join sys.all_objects
on all_objects.object_id = all_columns.object_id
where all_columns.name like '%$%'
It looks like renaming columns is done through a Stored Procedure, so you could take the output of that query to create a string of other queries to update all the offending records.
https://msdn.microsoft.com/en-us/library/ms188617.aspx
Good luck!
Powershell:
push-location;
import-module sqlps -disablenamechecking;
pop-location;
$s = new-object microsoft.sqlserver.management.smo.server '.';
$tbl = $s.databases['MyDB'].tables['MyTbl'];
foreach ($col in $tbl.Columns) {
if ($col -match '^Q([1-4])([0-9][0-9])\(\$\)$') {
$newName = "20$($matches[2]) Q$($matches[1])";
$col.Rename( $newName );
}
}

powershell and SQL

I am working with powershell and SQL using a query to extract drive information from a server
I am writing following query
set #sql = 'C:\WINDOWS\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -c "Get-WmiObject -Class Win32_Volume -Filter ''DriveType = 3'' | select name,label,capacity,freespace | foreach{$_.name+''!''+$_.label+''|''+$_.capacity/1048576+''%''+$_.freespace/1048576+''*''}"'
xp_cmdshell #SQL
i get following output
output
*******************************************************************************************
C:\!RISCDCC36N03C$|139980.3984375%35242.921875*
D:\!RISCDCC36N03D$|139977.99609375%34774.08984375*
G:\!RISCDCSQL552G|92151.9375%46329.1875*
M:\!|0%0*
M:\RISCDCSQL557BMP\!RISCDCSQL557BMP|81911.9375%31869.3125*
M:\RISCDCSQL557DMP\!RISCDCSQL557DMP|40954.9375%37753.5*
M:\RISCDCSQL557CMP\!RISCDCSQL557CMP|20475.9375%7643.375*
T:\!RISCDCSQL563T$|81911.9375%15462*
R:\!RISCDCSQL561R$|35836.9375%19392.0625*
P:\RISCDCSQL560BMP\!RISCDCSQL560BMP|225278.9375%15844.625*
P:\!RISCDCSQL560P$|245759.9375%13014.75*
P:\RISCDCSQL560CMP\!RISCDCSQL560CMP|122876.9375%29950.9375*
P:\RISCDCSQL560AMP\!RISCDCSQL560AMP|102398.9375%100423.25*
L:\!RISCDCSQL556L$|20479.9375%5072.1875*
I:\!RISCDCSQL553I$|512003.9375%81162.5*
I:\RISCDCSQL553MP1\!RISCDCSQL553MP1|307200.9375%137322.9375*
X:\RISCDCSQL567CMP\!RISCDCSQL567CMP|97288.9375%45540.125*
X:\!|0%0*
X:\RISCDCSQL567AMP\!RISCDCSQL567AMP|35841.9375%28526.125*
U:\!RISCDCSQL564U$|66552.9375%7892*
NULL
**************************************************************************
I don't understand why for M drive and X drive it is giving 0%0.
I am using this information to calculate further growth of space. while calculating it is givng me divide by zero.
( docs http://msdn.microsoft.com/en-us/library/windows/desktop/aa394515%28v=vs.85%29.aspx )
It looks like drive M and X each have a full volume/partition (no free space) amongst the others.
Remove them from the output with an extra filter clause -
-Filter ''DriveType = 3 and freespace>0''
That works for me, in the Powershell prompt...
PS C:\Windows\System32> Get-WmiObject -Class Win32_Volume -Filter 'DriveType = 3
and freespace>0' | select name,label,capacity,freespace