As a databases admin with a few dozen servers and a few hundred SQL Server database, I need to effectively build automated jobs to perform various administrative tasks such as backing up databases. I’m still new to PowerShell but I am beginning to see how immensely helpful it is to me and my work.

I found a good PowerShell script for backing up databases at this blog location. However, I wanted to change it slightly to accommodate backing up ALL, System, User, or a list of databases. Processing ALL, System, or User is straightforward enough but I had to it was the first time I came up against have to compare a value against a list of values. In SQL you simply use an IN operator with a list of values but I was not sure of how to accomplish the same process in PowerShell.

Here was my problem: the user could supply a list of databases to backup and the backup script has a line with captures all the database objects for that SQL Server instance. I need to backup only those which are in the users list.

I found that the PowerShell WHERE clause can use a -contains operator which effectively filters the selection for an array. To test the operation I set up a small script to build two arrays and then I piped one array through a WHERE filter of which the results are piped to a ForEach. The ForEach sees only the results of the WHERE which mimics the SQL IN operator.

Run this code in PowerShell to see what I mean.

$a = @("db1","db2","db3","db4")
$d = @("db1","db2","db3","db4","db5","db6","db7","db8")
$d | where { $a -contains $_ } | foreach { Write-Host $_ }

$a represents the list of database supplied by the user.
$d represents the array of databases returned when accessing the Microsoft.SqlServer.Management.Smo.Server object.
I can now back up the user supplied databases within the foreach script block.

This is a wonderful article which not only details the use of Compare-Object but also provides some very excellent examples on its use.

Tips & Tricks Using Compare-Object – Dreaming in PowerShell – PowerShell.com

I am very new to PowerShell but I am beginning to like using it considerably more each day. I recently had a need for a quick and easy way to script a process which would copy only new files from one location to another. after scouring the Internet for a good example, I stumbled upon the Compare-Object cmdlet and this excellent article.

The actual script I came up with is rather simple and serves my purpose exactly. As I  mentioned, I am new to PowerShell and there may very well be a better method. However, this one works for me.

The script code:

param(
    [string]$s = '\\serverx\c$\ProgramData\Polaris\3.5\SQLVS1\AuthorityUpdates',
    [string]$t = '\\servery\data03\shared\libraries\zmarc'
)

$target = Get-ChildItem $t
$source = get-childitem $s
Compare-Object $source $target -Property Name -PassThru |
    Where-Object { $_.SideIndicator -eq '<=' } |
    foreach-object -process{
        copy-item $_.FullName -destination $t
        }

connection.Up until recently, the only way I could get my Cisco VPN to work was to place my desktop in the DMZ. I really did not like having to do that. After considerable Internet searching, I could not find any information specific to my D-Link model (DIR 625) for allowing access using a Cisco VPN. Most of the information I was able to locate referenced other models and most made reference to making sure ‘VPN pass-through’ is enabled. Well, AFAIK, the DIR 625 does not have a ‘pass-through’ setting. Other information referred to forwarding port 10000 . However, those failed to mention port 10000 is only used when you configure the VPN to use TCP rather than UDP. My configuration was given to me by our network admin and it uses IPSec/UDP. When I tried to change it, the connection no longer worked even while in the DMZ. I could only conclude the target would only accept UDP.

After a couple of hours of experimentation, I was finally able to establish a connection without being in the DMZ. So that others who may happen to fall into the same situation have a solution, I am providing it here.

The very first thing you must do is to open your D-Link Admin screen, click the Advanced tab on top, and open the Inbound Filter on the left. You’ll need to create a new filter using the IP address where your VPN connects to. You can easily find this by looking at your D-Link log right after an unsuccessful  connection attempt (you’ll see the blocked attempt). An example of an Inbound Filter is given here but with my IP partially blocked. My source range is for one IP address. Pay attention to the ‘Name’ given, it will be used again.

image

After saving your inbound filter, you now need to open the Port Forwarding item on the left of your screen. You will then add a new rule to forward UDP ports 500 through mach zehnder modulator5000 65536 to your local machine using the filter created in the previous step. Its actually pretty easy because the filter name will be in the drop-down list for the Inbound Filter item. Take a look at this example screen shot:

imageдивани

Save your settings and you should now be able to use your Cisco VPN connection without resorting to using the DMZ.

This is one of those nasty little thorns that sticks you every once in a while.

You add a new SQL Server authentication login with Server Manager and you forget to uncheck the boxes for User must change password, Enforce password, and Enforce Expiration. Being this is an application user for which you don’t want to enforce password restrictions and which uses ODBC, therefore never seeing a login dialog, they never get an opportunity to change the password. Consequently the login can’t be used as is.
image

Ok, you realize your mistake too late. The login has been created. It has been associated with one or more databases and/or schemas. Permissions have been granted, etc., etc., etc. How do you fix it? Guess what? If you try to just want to uncheck the “User must change” check box, you can’t! It is greyed out.

This conundrum perplexed me to no end when first encountered. Searching the internet turned up several solutions like this one:
ALTER LOGIN test_must_change WITH PASSWORD = ‘newpass’,
      CHECK_POLICY = OFF,
      CHECK_EXPIRATION = OFF;

Guess what happens (you have three choices and the first two don’t count). You get this error message
Msg 15128, Level 16, State 1, Line 1
The CHECK_POLICY and CHECK_EXPIRATION options cannot be turned OFF when MUST_CHANGE is ON.

If you try to user Server Manager and just uncheck the ‘Enforce password policy’ or ‘Enforce password expiration’ boxes, you get this

THE FIX

You MUST change the password first and it must be done without changing the other password policy options. You CAN change the password to be the same as the existing one. However, you do it, you still must effect a change on the password an then change the policy options as a separate step. If you choose to use the Server Manager wizard, when you change the password, the ‘User must change password’ check box will become available and you can then uncheck it (do not uncheck the other policy check boxes if they already were). You can then save the change, open the wizard again, uncheck the other policy restrictions, and save it again.

If you decide to use a query, you can use code similar to this
USE Master
GO
ALTER LOGIN test_must_change WITH PASSWORD = ‘samepassword’
GO
ALTER LOGIN test_must_change WITH
      CHECK_POLICY = OFF,
      CHECK_EXPIRATION = OFF;

Error 604 happened during db open, shutting down database
USER: terminating instance due to error 604

I recently ran into this problem and because I could not find much relevant information to resolve it, I decide to write up my resolution process. I am not sure of all the reasons one can encounter a “604″ error and this process addresses a problem with corrupted blocks.

My Alert log contained an entry, just prior to the “604″, which indicated I had corrupt data blocks in my SYSTEM01.DBF data file.

Corrupt block relative dba: 0×00400037 (file 1, block 55) Fractured block found during buffer read Data in bad block: type: 0 format: 0 rdba: 0×00000000 last change scn: 0×0000.00000000 seq: 0×0 flg: 0×00 spare1: 0×0 spare2: 0×0 spare3: 0×0 consistency value in tail: 0×00001501 check value in block header: 0×0 block checksum disabled Reread of rdba: 0×00400037 (file 1, block 55) found same corrupted data Tue Sep 09 13:27:59 2008 Errors in file d:\oracle\product\10.2.0\admin\fmax\udump\fmax_ora_668.trc: ORA-00604: error occurred at recursive SQL level 2 ORA-01578: ORACLE data block corrupted (file # 1, block # 55) ORA-01110: data file 1: ‘E:\ORADATA\FMAX\ORADATA\FMAX\SYSTEM01.DBF’

At first I ‘googled” a search for the 604 error text and found meaningful information but no clear way of resolving it. Several suggestions referred to using the ‘START MOUNT’ followed with a ‘RECOVER DATABASE’. I tried that and the database did go through recovery but still would not start. After thinking about it a few minutes, I recalled using RMAN to recover corrupted blocks on an already running database. So, I said to myself: ‘Self, why not use RMAN again’? I knew the database would not open bu RMAN should be able to run against a ‘mounted’ database. I then issued the START MOUNT command in SQLPLUS, brought up another command window (this is a Windoze environment) and ran through the RMAN recover corrupt blocks process

RMAN> connect target connected to target database: FMAX (DBID=1458847106) RMAN> backup check logical validate database; Starting backup at 08-AUG-08 using target database control file instead of recovery catalog allocated channel: ORA_DISK_1 channel ORA_DISK_1: sid=245 devtype=DISK channel ORA_DISK_1: starting compressed full datafile backupset channel ORA_DISK_1: specifying datafile(s) in backupset input datafile fno=00005 name=E:\ORADATA\FMAX\ORADATA\FMAX\FMAX_DATA.DBF input datafile fno=00001 name=E:\ORADATA\FMAX\ORADATA\FMAX\SYSTEM01.DBF input datafile fno=00003 name=E:\ORADATA\FMAX\ORADATA\FMAX\SYSAUX01.DBF input datafile fno=00006 name=E:\ORADATA\FMAX\ORADATA\FMAX\TOOLS01.DBF input datafile fno=00002 name=E:\ORADATA\FMAX\ORADATA\FMAX\UNDOTBS01.DBF input datafile fno=00004 name=E:\ORADATA\FMAX\ORADATA\FMAX\USERS01.DBF channel ORA_DISK_1: backup set complete, elapsed time: 00:00:25 Finished backup at 08-AUG-08 RMAN> BLOCKRECOVER CORRUPTION LIST; Starting blockrecover at 08-AUG-08 using channel ORA_DISK_1 starting media recovery media recovery complete, elapsed time: 00:00:00 Finished blockrecover at 08-AUG-08 RMAN>

After completing the RMAN recovery, I then issued an ALTER DATABASE OPEN and the database opened just fine. I just hope this little bit of information may help any one else who encounters a similar problem.