Congratulations to Dimitar Dimitrov a MCP, MCDBA, and MCAD of Hebrosbank Plovdiv, Bulgaria, who won first prize of $100 for the best solution to the January Reader Challenge, "Deploying a Startup Parameter on All Servers." Only one submitter met the expectations set by the problem for the January challenge. Here’s a recap of the problem and the solution to the January Reader Challenge.

Problem:


Charlie is a database administrator who manages a combination of more than 50 installations of SQL Server 2000 and SQL Server 7.0. He wants to add a new trace flag as a startup parameter on all the servers to generate a report in the event of a SQL Server deadlock. For this problem, assume that the trace flag that generates this deadlock report is 1204. How can Charlie quickly deploy this new startup parameter to all the servers?

Solution:


Charlie can use the SQL Distributed Management Objects (SQL-DMO) API to connect to each SQL Server and add the new trace flag 1204 startup parameter, specifically the Configuration.Parameters collection of the SQLServer object. After connecting to a SQL Server instance by using the SQLServer object, the Configuration.Parameters collection is used to enumerate all the startup parameters currently configured. Charlie can then add the trace flag 1204 startup parameter to the Parameters collection. Below, a sample VBScript program, AddSqlStartup.vbs, shows how to use SQL-DMO to add a startup parameter to a SQL Server instance. Now Charlie can simply call AddSqlStartup.vbs for each server he wants to add the new startup parameter to. Charlie can do this by writing a command script using the FOR command to enumerate a list of servers specified in a text file and calling AddSqlStartup.vbs for each server. Alternatively, he can incorporate this logic into the VBScript program itself. The examples below show the implementation using a CMD script.

' AddSqlStartup.VBS
option explicit
dim sqlsrvr
dim startupparam
dim parameterscount
dim currentparams
dim paramfound
dim scriptargs

set scriptargs = WScript.Arguments
if scriptargs.count  2 then
    WScript.StdOut.WriteLine "Usage: AddSqlStartup "
    WScript.Quit
end if

set sqlsrvr = CreateObject("SQLDMO.SQLServer")
sqlsrvr.LoginSecure = True
sqlsrvr.Name = scriptargs(0)
sqlsrvr.Connect


paramfound = false
startupparam = scriptargs(1)

set currentparams = sqlsrvr.Configuration.Parameters
for parameterscount = 1 to currentparams.count
    if currentparams(parameterscount) = startupparam then
        paramfound = true
    end if
next

' Add new startup parameter if it doesn't exist.
if not paramfound then
    currentparams.add startupparam
end if

sqlsrvr.Disconnect
set sqlsrvr = Nothing

:: AddSqlStartup.CMD
@echo off
setlocal
set PARAM=%1
if "%1" EQU "" (
    echo Please specify the startup parameter.
    goto :eof
)

for /F %%S in (servers.txt) do (
    cscript //NoLogo AddSqlStartup.vbs %%S %PARAM%
)
Endlocal

File: Servers.Txt
srvr1
srvr2\yukon
srvr3

Finally, Charlie executes the CMD script (which reads the list of servers from the Servers.txt file and adds the startup parameter -T1204 to each server) by issuing the following command:

AddSqlStartup.CMD –T1204

Alternatively, Charlie can use the OLE automation system stored procedures to use DMO from within T-SQL to add the startup parameter. A sample stored procedure that shows how to add a new parameter is shown below:

CREATE PROCEDURE SetStartupParameter(@SqlServer varchar(255), @user varchar(255) =
NULL, @password varchar(255) = NULL, @value varchar(255) = '-T1204')
AS
  DECLARE @dmoSqlServer int, @parameters int, @hr int
  DECLARE @src varchar(255), @desc varchar(255)

  IF @value IS NULL BEGIN
    RAISERROR('The @value can not be null', 16, 1)
    RETURN
  END

  EXEC @hr = sp_OACreate 'SQLDMO.SQLServer', @dmoSqlServer OUT
  IF @hr  0 GOTO ExitProc

  -- Using windows authentication. The SQL Service account must be sysadmin
  -- on remote SQL Server (@SqlServer).
  IF @user IS NULL
    EXEC sp_OASetProperty @dmoSqlServer, 'LoginSecure', 1


  EXEC @hr = sp_OAMethod @dmoSqlServer, 'Connect', null, @SqlServer, @user, @password
  IF @hr  0 GOTO ExitProc

  EXEC @hr = sp_OAGetProperty @dmoSqlServer, 'Configuration.Parameters', @parameters OUT
  IF @hr  0 GOTO ExitProc

  -- Checking to see whether the startup parameter already exists.
  DECLARE @count int , @i int, @v varchar(255), @exists bit
  SELECT @exists = 0, @i = 1
  EXEC sp_OAMethod @parameters, 'Count', @count OUT
  WHILE @i  0 GOTO ExitProc
  END
  GOTO ExitProc

ExitProc:
  IF @hr  0 BEGIN
    EXEC sp_OAGetErrorInfo @dmoSqlServer, @src OUT, @desc OUT
    SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
  END
  EXEC sp_OADestroy @dmoSqlServer
  RETURN @hr
GO

FEBRUARY READER CHALLENGE:


Now, test your SQL Server savvy in the February Reader Challenge, "Imposing Data Restrictions" (below). Submit your solution in an email message to challenge@sqlmag.com by January 19. Umachandar Jayachandran, a SQL Server Magazine technical editor, will evaluate the responses. We’ll announce the winner in an upcoming SQL Server Magazine UPDATE. The first-place winner will receive $100, and the second-place winner will receive $50.

Problem:


Arun is a database architect who designs database schemas for products that use SQL Server 2000 and 7.0. Arun is currently working on a schema for a product that lets end users configure field names. The product’s schema table contains a column that stores a field name, and this field name is displayed in the product’s UI. The table can be installed under any case-insensitive database collation supported by SQL Server. The schema of the table looks like this:

create table meta_FieldNames ( fieldid int not null primary key, fieldname nvarchar(50) not null )

As part of the schema design, Arun wants to allow only a mix of upper or lowercase alphabetical characters with no numbers, international alphabet characters (e.g., accent marks, tildes) or special characters in the field names. How can he impose this restriction on the "fieldname" column of the table?