Category Archives: Imported from BeyondRelational

These posts are imported from my old blog page: http://beyondrelational.com/modules/2/blogs/77/nakuls-blog.aspx

#0255-SQL Server-Installation-Feature Discovery Report


Have you ever encountered a need to find and/or validate the SQL Server features and their respective patch levels for any given server running a single or multiple SQL Server instance(s)? If so, the Installed SQL Server Feature Discovery Report generation utility is just the tool you are looking for.


Today’s post show you how to use this small utility for your documentation/inventory purposes.



















Launch the SQL Server 2012 installer by clicking on the SQL Server Installation Center
[You can also run the installer from the setup disc]
image
Under “Tools”, you will find the “option to launch the “Installed SQL Server Features Discovery Report”
image
Clicking on the tool starts the processing and you will be presented with the progress dialog, standard to all progress operations of the SQL Server 2012 installer.
image
Once execution is complete, the report will be opened automatically in Internet Explorer
image

If you need to send this report over to your IT team or preserve it for documentation purposes, you can find a copy at:


Path for Discovery Report file: <<SQL Server installation path>>Setup BootstrapLog<<Date time>>SqlDiscoveryReport.htm


Example: C:Program FilesMicrosoft SQL Server110Setup BootstrapLog20130407_103300SqlDiscoveryReport.htm


I trust this quick post will be helpful to you in the future.


Until we meet next time,


Be courteous. Drive responsibly.

#0254-SQL Server 2000-Alternate to Table Valued Parameters-Share Temporary Tables with a stored procedure


Support for Microsoft SQL Server 2000 ends this year and yet, one can find systems (production or otherwise) that continue to run on and support SQL Server 2000. Recently, we were tasked with porting a piece of functionality backwards, i.e. from versions that support SQL Server 2012/2008 to SQL 2000/2005. Unfortunately, this piece of functionality was designed to work with newer versions of Microsoft SQL Server and involved the use of table valued parameters which is not possible in SQL Server 2000.

After a couple of hours of brain-storming, we realized that we could share temporary tables with the underlying stored procedures as long as the connection remained the same. Because the connection that created a temporary table is still active, the temporary table will continue to be accessible if the stored procedure is executed on the same connection. Here’s a small demo to help explain the solution.

Demo

For this demonstration, we will create a simple mathematical temporary table which will be updated from within a stored procedure. Assuming that the temporary table is named #tTableValues and has columns iA, iB and iC ( = iA * iB), let us first create a stored procedure which is designed to update the value of iA:

USE tempdb ;
GO
IF OBJECT_ID('UpdateTableValues') IS NOT NULL
DROP PROCEDURE dbo.UpdateTableValues
GO

CREATE PROCEDURE dbo.UpdateTableValues
@replacementValue INT
AS
BEGIN
SET NOCOUNT ON ;

IF OBJECT_ID('#tTableValues') IS NOT NULL
BEGIN
UPDATE tv
SET tv.iA = @replacementValue
FROM #tTableValues AS tv
END
ELSE
BEGIN
PRINT 'Temporary table: #tTableValues does not exist or access denied.'
END
END
GO

As you can see from the T-SQL script above, the stored procedure assumes that the temporary table is already available to it and directly makes the update. All the calling application now has to do is:

  1. Open a SQL Server connection, say C1
  2. Create the temporary table
  3. Insert data into the temporary table
  4. Call the stored procedure for the desired computation
  5. Fetch the value/result once the stored procedure execution is complete
  6. Drop the temporary table
  7. Close connection C1

The T-SQL script below demonstrates this workflow:

--1. Connection has been created
USE tempdb ;
GO
--2. Check for and create the required temporary table
IF OBJECT_ID('#tTableValues') IS NOT NULL
DROP TABLE #tTableValues
GO

CREATE TABLE #tTableValues
(
Id INT IDENTITY(1, 1)
PRIMARY KEY CLUSTERED,
iA INT,
iB INT,
iC AS iA * iB
) ;
GO

--3. Insert some test data
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 1 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 2 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 3 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 4 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 5 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 6 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 7 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 8 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 9 ) ;
INSERT INTO #tTableValues ( iA, iB )
VALUES ( 1, 10 ) ;
GO

--Debug point 01: Select from the temporary table
SELECT 'Debug Point 01' AS StepName,
Id,
iA,
iB,
iC
FROM #tTableValues ;
GO

--4. Execute the stored procedure
--NOTE that the connection has to be the same!
EXEC dbo.UpdateTableValues @replacementValue = 2 ;
GO

--5. Fetch the result of the stored procedure execution
SELECT 'Step 05 - Results' AS StepName,
Id,
iA,
iB,
iC
FROM #tTableValues ;

--6. Cleanup - the connection can now be closed
IF OBJECT_ID('#tTableValues') IS NOT NULL
DROP TABLE #tTableValues
GO

The screen-shot shown below shows the output of the execution and it can be seen that the value for iA in the temporary table created by the calling application was indeed updated by the stored procedure and the results were available after the stored procedure execution completed.

image

Conclusion

As demonstrated, temporary tables may be used for data exchange between an application and stored procedures or even between any two programmability objects (procedures, functions, etc). This functionality continues to remain valid even in the days of SQL Server 2012. The question, however is whether it would be preferable to use newer features like table valued parameters or not. Do let me know your thoughts on the same.

As for those who need to continue support of Microsoft SQL Server 2000 for their products, I trust this post was helpful.

Further Reading

Until we meet next time,

Be courteous. Drive responsibly.

#0253-SQL Server-HASHBYTES-String or binary data would be truncated: Msg 8152


Most enterprise products require that they be able to audit data modifications being made within the application. An important aspect of auditing is to be able to identify changes made outside of the application too, i.e. updates directly made on the data using a direct connection to the SQL Server instance. I recently authored a series of articles on SQLServerCentral.com around data change and tamper detection mechanisms available in Microsoft SQL Server. These are:

  • An in-depth look at change detection in SQL Server – Part 01 [Link]
  • An in-depth look at change detection in SQL Server – Part 02 [Link]
  • HASHBYTES: Is CHECKSUM really required? [Link]

Soon after the publication of these articles, a coincidence at work prompted me to write this post.

One of our application modules used HASHBYTES for detecting data change. We were receiving random reports that the quality assurance engineers were receiving auditing errors. As we tracked the issue down through the SQL Server Profiler, we noticed that the underlying error was a “simple” string truncation error:

Msg 8152, Level 16, State 10, Line 5
String or binary data would be truncated.

Root Cause

The following line from the Books-On-Line help for HASHBYTES [Link] caught our attention:

Allowed input values are limited to 8000 bytes.

As soon as we read it, things became very clear to us. Taking a quick look at the schema showed us that the underlying field being checked for changes was an NVARCHAR(MAX) field and the users were attempting to enter data greater than 4000 characters (i.e. 8000 bytes) causing the issue. As long as the data remained less than 4000 characters, no error was encountered.

A demo

The script below demonstrates the expected behaviour of HASHBYTES given that the input string is less than or equal to the 8000 byte limit. For the sake of brevity, I am using the REPLICATE function to create the string.

USE tempdb;
GO
--Declare an NVARCHAR((MAX) variable
DECLARE @tHashInputs NVARCHAR(MAX);
--Create a 4000 character string
SELECT @tHashInputs = CAST(REPLICATE('a',4000) AS NVARCHAR(MAX));

--Attempt to generate the HASHBYTEs value for this string
SELECT HASHBYTES('MD5',ISNULL(@tHashInputs,''));
GO

image

Now, let me alter the script such that the string being evaluated using HASHBYTES is greater than the 8000 byte limit, i.e. is 4001 characters for the NVARCHAR data-type:

USE tempdb;
GO
--Declare an NVARCHAR((MAX) variable
DECLARE @tHashInputs NVARCHAR(MAX);
--Create a 4000 character string
SELECT @tHashInputs = CAST(REPLICATE('a',4001) AS NVARCHAR(MAX));

--Attempt to generate the HASHBYTEs value for this string
SELECT HASHBYTES('MD5',ISNULL(@tHashInputs,''));
GO 

The following error is encountered upon executing the batch:

Msg 8152, Level 16, State 10, Line 5

String or binary data would be truncated.

As can be seen from the example above, HASHBYTES will fail for data beyond the documented 8000 character limit. Hence, areas like free-form comments may not be a suitable candidate for usage of HASHBYTES.

Solution

The only known workarounds that we have currently are:

  • Split the strings into multiple parts before generating the HASHBYTES value
  • Opt for any other change detection algorithm

Have you ever encountered such a situation before? If yes, what solution did you apply to overcome it?

References:

  • HASHBYTES – Books On Line page [Link]
  • An in-depth look at change detection in SQL Server – Part 01 [Link]
  • An in-depth look at change detection in SQL Server – Part 02 [Link]
  • HASHBYTES: Is CHECKSUM really required? [Link]

Until we meet next time,

Be courteous. Drive responsibly.

#0252 – Shutdown/Restart a local or remote server via command prompt


Today’s post is not SQL Server related, but is related to the underlying host operating system and it’s administration. When working on development projects, one may need to restart servers and/or workstations often. This becomes a challenge when one is working from remote locations or on virtual machines hosted on the network.


Today, I will show how to shutdown or restart a local or remote machine via the command prompt. In fact, you may be surprised (as are most people around me) to learn that this functionality exists since Windows 2000 (i.e. it’s more than a decade old!)


Remote Shutdown tool – SHUTDOWN.EXE


The windows operating system ships with a remote shutdown tool. It is a command line tool that can be used to shutdown or restart local and remote machines. In Windows Server 2003, this tool has been enhanced to also accept the reason for the shutdown.


The syntax and help for this tool can be obtained by going to the command prompt on the machine and typing:


shutdown /?


The tool allows administrators to:



  • Shutdown or restart a local machine

    • Shutdown: shutdown /s
    • Restart: shutdown /r

  • Shutdown or restart a remote machine

    • Shutdown: shutdown /s /m \MyRemoteMachine 
    • Restart: shutdown /r /m \MyRemoteMachine

  • Schedule shutdown/restart operations

    • Shutdown: shutdown /s /t 200
    • Restart: shutdown /r /t 200
    • The above examples set a timeout of 200 seconds before the shutdown/restart takes place

  • Specify a reason for the shutdown/restart

    • Planned: shutdown /s /d p:xx:yy
    • Unplanned: shutdown /s /d u:xx:yy
    • Where xx is the major reason number and yy is the minor reason number. For example, a shutdown due to application installation should have a major reason code of 4 and a minor reason code of 2
    • User can also specify a custom comment by using the /c swtich

  • Abort a system shutdown

    • shutdown /a

  • Log off from a local machine (remote logoff is not supported)

    • shutdown /l

  • Hibernate a local machine

    • shutdown /h

  • Force the operation

    • shutdown /s /t 200 /d p:4:2 /f

Further Reading: http://technet.microsoft.com/en-us/library/cc780360(v=ws.10).aspx


Until we meet next time,


Be courteous. Drive responsibly.


[EDIT: April 25, 2013, 0215IST – rectified the option for Hibernate.]

#0251 – SQL Server – Script to rename a database


Recently, one of my colleagues asked me a seemingly simple question:



I am facing issues in renaming a database – can you give me a script that can help me?


I was quite surprised at the question, but later realized why the issue was encountered. What had happened was that on our development servers, a database was restored, some data-cleanup work done and then the team wanted to run some pre-defined scripts on the database for checking and comparison purposes. These scripts were hard-coded to use a particular set of database names and therefore, the team wanted to rename the given SQL Server database.


However, what most of us don’t realize when working with the SQL Server Management Studio (SSMS) is that it opens up multiple connections to a given database. In this particular case also, the query editor’s connection was open which was causing issues with database renaming.


I therefore provided the team with the following script, which essentially takes the database into single-user mode and then renames the database to avoid any issues being caused by multiple open connections.

–Important: This changes the database context to master.
–If the user database remains in use, the rename will not succeed
USE master;
GO
–Now, take the DB in single-user mode
ALTER DATABASE AdventureWorks2008R2 SET SINGLE_USER;
GO
–Now, rename the DB
USE master;
GO
ALTER DATABASE AdventureWorks2008R2 MODIFY NAME = MyAdWrks2008R2;
GO
–Now, bring the database back to multi-user mode
–Caution: Use the new name here because the database would have already been renamed
USE master;
GO
ALTER DATABASE MyAdWrks2008R2 SET MULTI_USER;
GO

–Do not forget to apply necessary permissions again


Further Reading:


In the same context of SSMS and related connections, some of my previous posts might interest you:



Until we meet next time,


Be courteous. Drive responsibly.