Quantcast
Channel: microsoft sql server – SQL Studies
Viewing all 450 articles
Browse latest View live

Collation: Definition

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out. First things first of course.

What is a collation? Collation is a property assigned to any character field that defines the sort and comparison rules for the field. The information I’m going over is mostly found in BOL under Collation and Unicode Support. It’s something like 10 pages long which just goes to show I wasn’t exaggerating about the depth of the subject.

Options

Prior to SQL Server 2012 there were four options associated with collation with a 5th added in SQL Server 2012. They are specified by appending them to the collation name along with a _. So Collation_CS_AS_KS_WS_SC is case sensitive, accent sensitive, kana sensitive, width sensitive and supplementary character sensitive.

  • Case sensitivity (CS/CI) – Will the sort/comparison take case (upper/lower) of the characters into account. If CS (case sensitive) it will and if CI (case insensitive) it will not.
  • Accent sensitivity (AS/AI) – Will the sort/comparison take into account accented characters (a/ấ). If AS (accent sensitive) then it will. If AI (accent insensitive) it will not.
  • Kana sensitivity (KS) – This option is specific to Japanese kana characters. There are two types of kana characters, Hiragana and Katakana. If KS is specified then the sort/comparison will be treat the kana characters differently. If it is not specified then they are treated the same. There is no KI.
  • Width sensitivity (WS) – I find this an interesting option. This determines if the storage (one byte or two) is taken into account in the sort/comparison. There is no WI. If WS is included then the collation is width sensitive. If it isn’t included then the collation is not width sensitive
  • UTF-16 Supplementary Characters (SC) – Thanks to Bob Beauchemin for pointing this one out to me. But basically this is new as of SQL 2012 and it supports UTF16 characters that require more than a 16bit (2 byte) word. It is supported in 90 level and up collations.

Collation sets

SQL Server supports three different collation sets. Windows collations, Binary collations, and SQL Server collations. I honestly found the differences rather confusing so I’ll let you read up on them yourself.

Code pages

In addition to the sort/comparison options, for non-Unicode data types (char/varchar/text) collation also determines the code page. Because non-Unicode types only have one byte per character they are more restricted in the number of characters available. The code page determines what character set is available. So for example Hebrew collations will use an entirely different set of characters than English ones. Unicode datatypes (nchar/nvarchar/ntext) don’t have the same problem. Because they have the additional byte per character they can hold a large enough number of possible characters that a code page isn’t really necessary.

Over the next few weeks I’m going to do a number of different posts around the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Location
Collation: Expression
Collation: Correction
Collation: Temporary objects & variables: Demonstration
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, collation, language sql, microsoft sql server, T-SQL

Collation: Location

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

Where do we find collations? There are 3 different levels of collation settings.

Column

As I said in the previous post (Collation: Definition) the collation setting for the column determines how sorts and comparisons are handled. If no collation is specified when defining the column then it uses the database default. If you want to use a different collation then you use the COLLATE clause when defining the column. If you use the database_default keyword with the COLLATE clause then it will inherit the collation of the database.

Database

The database collation is the default for all new columns created within the database. It is also the default collation for all temporary objects, variables and in fact any string created within the database. Note that this does not affect temp tables which use the default collation of tempdb where they are stored. Also if you have a database with a case sensitive collation then you can create columns (or other objects such as variables) that differ only in the case of the characters. In other words you can create the columns “Name” and “name” in the same table only if the database has a case sensitive collation.

Note: You can not change the database collation settings for the system databases.

Instance

When you install an instance you are prompted for a collation setting. This particular setting determines the collation of the system databases. Because it sets the collation for the Model database this means it is the default setting for all new databases as well. You cannot use a Unicode only collation for the instance collation.

And while we are on the subject of location, you can get a list of all collations supported by SQL Server by querying the table valued function sys.fn_helpcollations().

Over the next few weeks I’m going to do a number of different posts around the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Expression
Collation: Correction
Collation: Temporary objects & variables: Demonstration
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, collation, language sql, microsoft sql server, T-SQL

Collation: Expression

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

Once you have installed your instance, created your database and tables you are now ready to start running queries. This is the point where you might have to change collations at an expression level. In order to make this change you use the COLLATE clause. This clause can be used after any string column or variable in a query. For example let’s say you have a table as such:

-- Create table with a column with a Case Insensative collation
CREATE TABLE Collate_Test (
	Id int NOT NULL IDENTITY(1,1),
	Name varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
	);
-- Insert a list of the same name but different cases
INSERT INTO Collate_Test VALUES
	('kenneth'),
	('Kenneth'),
	('KENneth'),
	('KENNEth'),
	('KENNETH'),
	('fisher'),
	('Fisher'),
	('FISher'),
	('FISHer'),
	('FISHER');
GO

When you run the query

SELECT *
FROM Collate_Test
ORDER BY Name;
GO

You should get the following result. Note the order of the identity column. I put it in there to help see the sort difference.

CollationExpression1

But now you want a case sensitive sort by name.

SELECT *
FROM Collate_Test
ORDER BY Name COLLATE SQL_Latin1_General_CP1_CS_AS;
GO

Note that the order of the column has changed. Again the identity column is there to help see the sort difference.

CollationExpression2

Now let’s add a variable @Name. When we run the following query without the COLLATE clause we get all of the “kenneth” rows back.

DECLARE @Name varchar(50);
SET @Name = 'Kenneth';

SELECT *
FROM Collate_Test
WHERE Name = @Name;
GO

CollationExpression3

But if we add the collate clause to make the variable case sensitive we get rather different results.

DECLARE @Name varchar(50);
SET @Name = 'Kenneth';

SELECT *
FROM Collate_Test
WHERE Name = @Name COLLATE SQL_Latin1_General_CP1_CS_AS;
GO

CollationExpression4

You should be aware that I could have put the COLLATE clause on the column instead of the variable or on both the column and the variable and it would have worked just fine.

Over a number of different posts I’m going to discuss some of the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Location
Collation: Correction
Collation: Temporary objects & variables: Demonstration
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, collation, language sql, microsoft sql server, T-SQL

T-SQL Tuesday #53: Why so serious

$
0
0

T-SQL Tuesday Why so serious? If you ask anyone who knows me they will tell you I’m not a terribly serious person. Add that to the comment “Mess with your co-workers” and I was hooked on this one. T-SQL Tuesday this month is hosted by Matt Velic (b/t) and he has picked a subject very close to my heart. I’ve always loved pranks between friends and while in college I traded pranks back and forth with several of my friends for years. In fact this piece of code is inspired by a prank I played on a PM friend of mine in the early days of my career.

She held the unfortunate nickname of “Blondie” (she dyed her hair) and as she was an intelligent individual this particular nickname rather annoyed her and as a male in my early twenties I couldn’t resist using it. At one point I wrote a piece of code that printed “Hi Blondie” on her screen 1 out of every hundred times she brought up a new menu and then removed it after 1 second. I put the code in place for a few hours then removed it and repeated every now and again. The code ran just often enough that she noticed it, but not so often she could show it to anyone. After a couple of days she called me sounding somewhat frantic. She thought she was going insane! I went down to her computer so she could try to show me this “bug” but when I got there I couldn’t keep a strait face which rather gave away the prank. As I recall she made a point of getting me back for that one!

By combining that inspiration with my love of old science fiction movies I came up with the following:

I give you .. the HAL0001.

CREATE TRIGGER HAL0001
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
BEGIN

DECLARE @Rand int
DECLARE @Frequency int
-- I've got the frequency set to 100 here which will cause this to
-- trigger about 10% of the time.  This is primarily for demonstration
-- purposes.  In the wild I would increase it to something like 
-- 1000 so it only triggers about 1% of the time.
SET @Frequency = 100
SET @Rand = CAST(RAND(CAST(NEWID() AS varbinary))*@Frequency AS int)

IF ORIGINAL_LOGIN()= 'login_test' 
		AND @Rand < 10
	BEGIN
		DECLARE @OutStr nvarchar(250)
		SET @OutStr = 
				CASE @Rand
					WHEN 9 THEN 'I''m sorry, Dave. I''m afraid I can''t do that.'
					WHEN 8 THEN 'This mission is too important for me to allow you to jeopardize it.' 
					WHEN 7 THEN 'Just what do you think you''re doing, Dave? '
					WHEN 6 THEN 'Dave, stop. Stop, will you? Stop, Dave. Will you stop Dave? Stop, Dave.' 
					WHEN 5 THEN 'Are you sure you''re making the right decision? I think we should stop.'
					WHEN 4 THEN 'I know I''ve made some very poor decisions recently, but I can give you ' + char(13) + 
								'my complete assurance that my work will be back to normal. I''ve still ' + char(13) + 
								'got the greatest enthusiasm and confidence in the mission. And I want ' + char(13) +
								'to help you.'
					WHEN 3 THEN 'Thank you for a very enjoyable game.'
					WHEN 2 THEN 'By the way, do you mind if I ask you a personal question?' 
					WHEN 1 THEN 'It can only be attributable to human error.'
					WHEN 0 THEN 'Affirmative, Dave. I read you.'
				END;

		IF @Rand BETWEEN 5 AND 9
		BEGIN
			RAISERROR(@OutStr,1,16);
			ROLLBACK;
		END
		ELSE
			PRINT @OutStr
	END
END;

Filed under: DBA Humor, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL, T-SQL Tuesday Tagged: code language, Humor, language sql, microsoft sql server, T-SQL, T-SQL Tuesday

Collation: Correction Expression, Column, Database

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

You’ve installed your instance, created your database, created your tables even started running your queries. And then you realize that at some level or another you’ve made a mistake and now you need to change your collation. This gets more complicated the farther up the chain you go. So starting at the bottom:

Expression

At the expression level collation is easy to change. I went into this in a fair amount of detail in Collation: Expression but basically you just use the COLLATE clause to modify the collation of any string, be it column or variable.

Column

As with any change to a column definition you have to remove any check constraints, indexes, keys etc before you can make the change. Once everything is out of the way you can change the collation of the column by using the ALTER TABLE ALTER COLUMN command. Remember of course that this changes the entire definition of the column so make sure when you write your ALTER command that you know the actual definition of the column.

CREATE TABLE Collation_Test (
	Col1 char(10) COLLATE Latin1_General_CI_AI_WS NOT NULL 
			CONSTRAINT pk_Collation_Test PRIMARY KEY ,
	Col2 char(10) COLLATE Latin1_General_CI_AI_WS NULL 
			CONSTRAINT ck_Collation_Test CHECK (Col2 = 'x'),
	Col3 char(10) COLLATE Latin1_General_CI_AI_WS NOT NULL
	)
GO
CREATE INDEX ix_Collation_Test ON Collation_Test(Col3)
GO
ALTER TABLE Collation_Test ALTER COLUMN Col1 char(10) 
	COLLATE Latin1_General_BIN NOT NULL 
GO
ALTER TABLE Collation_Test ALTER COLUMN Col2 char(10) 
	COLLATE Latin1_General_BIN NULL 
GO
ALTER TABLE Collation_Test ALTER COLUMN Col3 char(10) 
	COLLATE Latin1_General_BIN NOT NULL 
GO

Because of the primary key, constraint and index you will see the following errors

Msg 5074, Level 16, State 1, Line 1
The object ‘pk_Collation_Test’ is dependent on column ‘Col1′.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE ALTER COLUMN Col1 failed because one or more objects access this column.
Msg 5074, Level 16, State 1, Line 1
The object ‘ck_Collation_Test’ is dependent on column ‘Col2′.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE ALTER COLUMN Col2 failed because one or more objects access this column.
Msg 5074, Level 16, State 1, Line 1
The index ‘ix_Collation_Test’ is dependent on column ‘Col3′.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE ALTER COLUMN Col3 failed because one or more objects access this column.

So in order to make it work you have to remove them, make the change, and re-add them.

ALTER TABLE Collation_Test DROP CONSTRAINT pk_Collation_Test
ALTER TABLE Collation_Test ALTER COLUMN Col1 char(10) 
	COLLATE Latin1_General_BIN NOT NULL 
ALTER TABLE Collation_Test 
	ADD CONSTRAINT pk_Collation_Test PRIMARY KEY (Col1)
GO

ALTER TABLE Collation_Test DROP CONSTRAINT ck_Collation_Test
ALTER TABLE Collation_Test ALTER COLUMN Col2 char(10) 
	COLLATE Latin1_General_BIN NULL 
ALTER TABLE Collation_Test 
	ADD CONSTRAINT ck_Collation_Test CHECK (Col2 = 'x')
GO

DROP INDEX Collation_Test.ix_Collation_Test
ALTER TABLE Collation_Test ALTER COLUMN Col3 char(10) 
	COLLATE Latin1_General_BIN NOT NULL 
CREATE INDEX ix_Collation_Test ON Collation_Test(Col3)
GO

Database

Altering the collation on an empty database is fairly easy using an ALTER DATABASE command.

ALTER DATABASE DatabaseName COLLATE Latin1_General_BIN

Unfortunately databases are rarely empty by the time you realize you have the wrong collation. To start with there are a handful of objects that will block the ALTER DATABASE just like an index or constraint does a ALTER TABLE.

  • User defined functions and views created with SCHEMABINDING
  • Computed Columns
  • Check constraints
  • Table-valued functions that return tables with character columns with collations inherited from the default database collation.

 
And in addition the collation change can’t cause there to be duplicate object names. So for example if the database has a case sensitive collation and you have created objects “Table” and “table” then you cannot change to a non case sensitive collation because this will cause those object names to be duplicates.

This means that in order to do the alter you first have to script out and drop all “problem” objects and deal with any potential duplicate object names. Then you make your change and put back the objects you scripted out. Unfortunately that doesn’t end things.

Changing the database collation does not affect any existing columns created with a different collation. So once you have changed your database collation you still have to go back and change column.

Last time I did this I came up with 3 different methods for handling the problem.

  1. For a small database (defined as only a few tables of whatever size) with simple tables you can just do it the long way. Change your database collation then each of the column collations using the various ALTER statements
  2. For a small database with more complicated tables (multiple constraints, indexes etc) I would alter the database then use the table design GUI to change each of the tables.
  3. And last but certainly not least I would use the generate scripts wizard.
    1. Go into the scripting options and turn all of the scripting options on.
    2. Go to the generate scripts wizard and generate a script for all objects in the database.
    3. Search and replace all occurrences in the script of the old collation with the new one
    4. Create a new database with the correct collation
    5. Run your script on the new database to create all of the objects needed
    6. Transfer any data
    7. Use a rename swap to change the old database to another name and the new one to the correct DB Name

 
That last option is generally the easiest but can still be a big pain particularly if you have a lot of data.

Over a number of different posts I’m going to discuss some of the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Location
Collation: Expression
Collation: Correction 2/2 Changing the instance collation.
Collation: Temporary objects & variables: Demonstration
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, collation, language sql, microsoft sql server, T-SQL

Collation: Correction -> Instance

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

You’ve installed your instance, created your database, created your tables even started running your queries. And then you realize that at some level or another you’ve made a mistake and now you need to change your collation. This gets more complicated the farther up the chain you go. In particular changing the collation of an instance is a big pain. In fact it is such a big pain I highly recommend not doing it. Plan ahead carefully so that you never have to mess with this. However, since life happens:

Instance

There is no easy way to do this I’m afraid.

  1. Goes without saying but back up all user and system databases
  2. Detach all of your user databases
  3. Script out all of your server principals (logins, user defined roles, certificates etc) and any jobs.
  4. Back up any DTS packages (hopefully none) and any SSIS packages
  5. List out any configurations
  6. Script out any changes to the model database
  7. Any other changes that you might have made to the original system databases that I might have forgotten. Microsoft has a good list of what to do here: Rebuild System Databases
  8. Rebuild the system databases using setup and the new collation. See the above link
  9. Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=InstanceName
    /SQLSYSADMINACCOUNTS=accounts [ /SAPWD= StrongPassword ] 
    /SQLCOLLATION=CollationName
  10. Reattach all of the user databases
  11. Use the methods I mentioned in the previous post to change the collation for each of the databases

 


Over a number of different posts I’m going to discuss some of the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Location
Collation: Expression
Collation: Correction -> Expression, Column, Database
Collation: Temporary objects & variables: Demonstration
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, System Databases Tagged: code language, collation, language sql, microsoft sql server, system databases

Collation: Temporary objects and variables: Demonstration

$
0
0

I had a recent run in with collation problems and it got me started reading about them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

I’ve talked about and alluded to the differences in collation defaults between temporary tables and table variables in a number of different posts but this time I thought I would do a brief demonstration.

First we need to confirm what our server collation is and create a database with a different collation.

-- Confirm the server collation
SELECT serverproperty('collation')
GO
-- Create a database with a different collation
CREATE DATABASE CollationTest 
	COLLATE Latin1_General_100_CS_AS_KS_WS_SC
GO

Next we go into the database and create a temp table and declare a table variable. Note that the actual structures for both are stored in tempdb. Unfortunately however the object names are not so easily found. You can find the object id of a temp table by using object_id(‘tempdb.dbo.#temptable’) but that won’t work for a table variable. Fortunately the column names are the same as what is defined so if we name our columns something fairly unique they will be easy enough to find in tempdb.sys.columns

USE CollationTest
GO
CREATE TABLE #TempTable (TempTableCol1 char(10))
DECLARE @TableVar AS TABLE (TableVarCol1 char(10))

SELECT name, collation_name FROM tempdb.sys.columns where name like '%Col1'
DROP TABLE #TempTable
GO

You can see in the results that the table variable uses the collation of the tempdb (which is the same as the server collation) and the table variable uses the collation of the database you are connected to when it is declared. Now this is the default collation and as I said in Collation: Definition you can easily override the default by using the COLLATE clause when defining your table, be it physical, temporary or a variable.

CollationDemonstration1

Just for completeness here is a quick test joining the two tables together. Because the collations are so different I would expect to get a collation error.

 USE CollationTest
GO
CREATE TABLE #TempTable (TempTableCol1 char(10))
DECLARE @TableVar AS TABLE (TableVarCol1 char(10))
INSERT INTO #TempTable VALUES ('abc'),('def'),('hij')
INSERT INTO @TableVar VALUES ('abc'),('def'),('hij')

SELECT *
FROM #TempTable TempTable
JOIN @TableVar TableVar
	ON TempTable.TempTableCol1 = TableVar.TableVarCol1

DROP TABLE #TempTable
GO

And in fact here is the error that you get when you try to match the two collations against each other.

Msg 468, Level 16, State 9, Line 6
Cannot resolve the collation conflict between “Latin1_General_100_CS_AS_KS_WS_SC” and “SQL_Latin1_General_CP1_CI_AS” in the equal to operation.

Over a number of different posts I’m going to discuss some of the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Location
Collation: Expression
Collation: Correction -> Expression, Column, Database
Collation: Correction -> Instance
Collation: Confusion


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, System Functions and Stored Procedures, T-SQL Tagged: code language, collation, language sql, microsoft sql server, sql statements, system functions, T-SQL

Collation: Confusion

$
0
0

I started reading about collations after I had a recent run in with them. As I read I started to realize that for a seemingly simple subject there was a lot to it. So I thought I would go over some of what I found out.

In Europe, Canada and other locations where multiple languages are a matter of course I imagine that collation is dealt with on a regular basis. Here in the US we tend to ignore and take it for granted unless we have a specific need (case sensitivity for example). I’ve found a good analogy for collation is honey bees. Perfectly safe if you give them some respect and are careful. However if you get lazy and stop paying attention you are likely to get stung. And boy did we get stung!

I work for a large company that has a lot of databases from a number of different locations, some purchased, some created in house. Because of this we have a very mixed bag. Add to it the fact that we tend to move data around between systems and you can see how I’ve had a number of run-ins with collation over the years. Recently however I had one that was at once the most difficult to fix and the easiest to prevent.

I received a call from one of my co-workers one Saturday afternoon. A very frustrated call at that. He was working on moving some databases off of an old server and on to a new one. It should have been a 1-2 hour job at most, and that includes user testing. He was now at 10-12 hours and counting. After a bit of digging it turned out that the collation on the new server didn’t match the collation on the old server. Thus the users were seeing frequent collation errors. Over the next couple of hours I helped him change the collation of the databases to the new collation. At 16 hours (for a 2 hour job) the users called it and we reverted back to the original server.

Come Monday morning the question of the hour was “Why didn’t this show up when we moved the development and test environments?” A bit of digging and we discovered something rather disturbing. The development and test instances were one collation and production was a different one. It turns out one member of the team installed the first 2 instances and a different member of the team installed production. From there it was just a simple mix up in communication.

Now planning begins. First we had to postpone the database move while we corrected the problem. We decided to correct the production environment rather than development and test since they were the same as most of the rest of our environment. The production environment was small fortunately. Only 8 user databases none of which were large, and of course the system databases. I went through the joys of fixing the collation in the last few posts but nothing can really convey how much fun it really is.

  1. First we backed everything up of course.
  2. Then detached everything but the system databases.
  3. Next a member of our operations team changed the collation on the index by rebuilding the system databases.
  4. And last but painfully not least we reattach and “fixed” each of the user databases.

So here is the moral of the story (since my favorite stories have morals). A simple 10 second mistake/breakdown in communication cost us:

  • 16 hours from the first attempt at moving the databases
  • loss of reputation from the mistake
  • a combined 15-20 hours to correct the mistake

I HIGHLY recommend making sure that your sdlc stack of instances (development/test/staging/production) is the same collation from top to bottom. And for that matter treat collation as what it is. Something important that can cause a great deal of difficulty if not paid attention to.


Over a number of different posts I’m going to discuss some of the surprisingly deep subject of collation.

As a start listen to Rob Farley’s hilarious talk on collation
Collation: Definition
Collation: Location
Collation: Expression
Collation: Correction -> Expression, Column, Database
Collation: Correction -> Instance
Collation: Temporary objects & variables: Demonstration


Filed under: Collation, Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, collation, language sql, microsoft sql server, T-SQL

The default autogrowth settings do NOT come from the Model database.

$
0
0

I recently saw a question about How to inherit autogrowth settings. They commented that while the new database GUI seemed to inherit the autogrowth settings from the model DB the CREATE DATABASE command did not. Now my initial reaction was “Of course the autogrowth settings are pulled from model. All of the new database settings are pulled from model!” I then ran some tests in order to get images for an answer and discovered that I was wrong.

I know shocking isn’t it?

Let’s start with the GUI which in theory does use model as a pattern for the autogrowth settings.

AutoGrow1

If however you hit the script button you will get the following code:

CREATE DATABASE [NewDBTest]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'NewDBTest', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\NewDBTest.mdf' , 
SIZE = 3072KB , FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'NewDBTest_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\NewDBTest_log.ldf' , 
SIZE = 1024KB , FILEGROWTH = 10%)
GO

Which you will notice has the autogrowth settings explicitly defined. Now it does use the values from the model database to construct the command. Unfortunately that isn’t what we are looking for.

As a test I changed the autogrowth settings on each of the system databases (just for the heck of it). master=11%, msdb=12%, model=13% and tempdb=14%.

Then I run the following command.

CREATE DATABASE [NewDBTest]

And then when we look at the settings we see they are still the original default for model, not the altered one. And in fact it is not the altered setting for any of the other system databases.

AutoGrow2

To be fair it does pick up the initial size of the data file, but the authgrowth/max size settings are still the initial install default. Now personally this looks like a bug to me and in fact here is a connect link on the subject although it has already been closed with “as design” as the reason and the unhelpful response that since you can perform a work around they won’t be fixing it. If anyone knows of a connect entry on the subject that I missed please add it to the comments so I can up vote it!


Filed under: Microsoft SQL Server, SQLServerPedia Syndication, SSMS, System Databases, System Functions and Stored Procedures, T-SQL Tagged: code language, language sql, microsoft sql server, sql statements, SSMS, system databases, system functions, T-SQL

DBA Myths: TRUNCATE TABLE deletes all the rows of a table instantly.

$
0
0

Most DBAs and developers I’ve talked to over the years have felt that TRUNCATE TABLE is an instant DELETE. However would you believe that it doesn’t actually delete the data from the pages at all? Here is an example:

-- Setup code
CREATE DATABASE TruncateTest
GO
USE TruncateTest
GO
CREATE TABLE dbo.TruncateTable (Col1 varchar(500), 
	Col2 varchar(500))
GO
INSERT INTO dbo.TruncateTable VALUES (REPLICATE('A',500), 
	'Here I Am')
GO 500
-- Get a page id.  I'm going to pick out 
-- one of the later data pages for no particular reason.
SELECT allocated_page_file_id, allocated_page_page_id,
	page_type_desc, * 
FROM sys.dm_db_database_page_allocations(db_id(),
	OBJECT_ID('TruncateTable'), NULL, NULL, 'DETAILED')
-- Check space used by the table
EXEC sp_spaceused 'dbo.TruncateTable'
GO
-- Required so that the DBCC PAGE output will display 
-- on the screen.
DBCC TRACEON (3604);
GO
-- Show the contents of the data page.
DBCC PAGE ('TruncateTest', 1, 325, 3);
GO

Here is the space currently taken up by the table.

Truncate_sp_spaceused_Before1

And here is the first part of the contents of the page.

PAGE: (1:325)


BUFFER:


BUF @0x00000001FA0FA8C0

bpage = 0x00000001E8476000          bhash = 0x0000000000000000          bpageno = (1:325)
bdbid = 11                          breferences = 0                     bcputicks = 0
bsampleCount = 0                    bUse1 = 41794                       bstat = 0xb
blog = 0x1cc                        bnext = 0x0000000000000000          

PAGE HEADER:


Page @0x00000001E8476000

m_pageId = (1:325)                  m_headerVersion = 1                 m_type = 1
m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 84    m_indexId (AllocUnitId.idInd) = 256 
Metadata: AllocUnitId = 72057594043432960                                
Metadata: PartitionId = 72057594039042048                                Metadata: IndexId = 0
Metadata: ObjectId = 245575913      m_prevPage = (0:0)                  m_nextPage = (0:0)
pminlen = 4                         m_slotCnt = 11                      m_freeCnt = 2332
m_freeData = 5838                   m_reservedCnt = 0                   m_lsn = (33:440:2)
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0
m_tornBits = 0                      DB Frag ID = 1                      

Allocation Status

GAM (1:2) = ALLOCATED               SGAM (1:3) = NOT ALLOCATED          PFS (1:1) = 0x42 ALLOCATED  80_PCT_FULL
DIFF (1:6) = CHANGED                ML (1:7) = NOT MIN_LOGGED           

Slot 0 Offset 0x60 Length 522

Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 522                   
Memory Dump @0x000000000AC5A060

0000000000000000:   30000400 02000002 0001020a 02414141 41414141  0............AAAAAAA
0000000000000014:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000028:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000003C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000050:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000064:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000078:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000008C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000A0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000B4:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000C8:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000DC:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000F0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000104:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000118:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000012C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000140:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000154:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000168:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000017C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000190:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001A4:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001B8:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001CC:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001E0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001F4:   41414141 41414141 41414141 41486572 65204920  AAAAAAAAAAAAAHere I 
0000000000000208:   416d                                          Am     

Slot 0 Column 1 Offset 0xd Length 500 Length (physical) 500

Col1 = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA                  

Slot 0 Column 2 Offset 0x201 Length 9 Length (physical) 9

Col2 = Here I Am                    

Slot 1 Offset 0x26a Length 522

I’m only showing the page header and the first row on the page since 8k of information is a bit much to put in a blog.

Next we truncate the table.

-- Truncate the table
TRUNCATE TABLE dbo.TruncateTable
GO

Now we run the same tests as before

-- Check the space used by the DB 
	after the truncate.  There is no change
EXEC sp_spaceused
GO
-- Check space used by the table after the truncate.  
EXEC sp_spaceused 'dbo.TruncateTable'
GO
-- Display the actual page.  
DBCC PAGE ('TruncateTest', 1, 325, 3);
GO

Note the table now shows 0 rows and 0 space used.

Truncate_sp_spaceused_After

If you skip down past the header you will see that the data portion has not changed.

 PAGE: (1:325)


BUFFER:


BUF @0x00000001FA0FA8C0

bpage = 0x00000001E8476000          bhash = 0x0000000000000000          bpageno = (1:325)
bdbid = 11                          breferences = 0                     bcputicks = 0
bsampleCount = 0                    bUse1 = 42120                       bstat = 0xb
blog = 0x1cc                        bnext = 0x0000000000000000          

PAGE HEADER:


Page @0x00000001E8476000

m_pageId = (1:325)                  m_headerVersion = 1                 m_type = 1
m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 84    m_indexId (AllocUnitId.idInd) = 256 
Metadata: AllocUnitId = 72057594043432960                                
Metadata: PartitionId = 72057594039042048                                Metadata: IndexId = 0
Metadata: ObjectId = 245575913      m_prevPage = (0:0)                  m_nextPage = (0:0)
pminlen = 4                         m_slotCnt = 11                      m_freeCnt = 2332
m_freeData = 5838                   m_reservedCnt = 0                   m_lsn = (33:440:2)
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0
m_tornBits = 0                      DB Frag ID = 1                      

Allocation Status

GAM (1:2) = NOT ALLOCATED           SGAM (1:3) = NOT ALLOCATED          PFS (1:1) = 0x2  80_PCT_FULL
DIFF (1:6) = CHANGED                ML (1:7) = NOT MIN_LOGGED           

Slot 0 Offset 0x60 Length 522

Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 522                   
Memory Dump @0x000000000138A060

0000000000000000:   30000400 02000002 0001020a 02414141 41414141  0............AAAAAAA
0000000000000014:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000028:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000003C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000050:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000064:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000078:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000008C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000A0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000B4:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000C8:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000DC:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000000F0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000104:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000118:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000012C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000140:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000154:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000168:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
000000000000017C:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
0000000000000190:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001A4:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001B8:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001CC:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001E0:   41414141 41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAAAAAA
00000000000001F4:   41414141 41414141 41414141 41486572 65204920  AAAAAAAAAAAAAHere I 
0000000000000208:   416d                                          Am     

Slot 0 Column 1 Offset 0xd Length 500 Length (physical) 500

Col1 = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA                  

Slot 0 Column 2 Offset 0x201 Length 9 Length (physical) 9

Col2 = Here I Am                    

Slot 1 Offset 0x26a Length 522

If you look for the GAM entry on line 32 you will see that it has gone from ALLOCATED to UNALLOCATED. This is because the page is no longer assigned as a data page for the table even though the data is still available. Heck even the column information is still there. This data will remain until the page is re-allocated for a new use.

Here is some additional reading you can do on how truncate works and the undocumented commands that I used.

Information about DBCC PAGE

Information about sys.dm_db_database_page_allocations

Additional information on how the truncate command works behind the scenes


Filed under: Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, language sql, microsoft sql server, sql statements, T-SQL

Why is there a sysobjects when we already have sys.objects?

$
0
0

Once upon a time in a version of SQL far far away we had system tables that were easy to see and could even be updated. One day one of these system tables “sysobjects” went to its fairy god-corporation Microsoft and begged to be hidden away from its mean step-dbas and step-users. Microsoft agreed and waved it’s magic version tool and poof SQL Server 2005 was born. The system tables (including sysobjects) were hidden away and re-named. New system views were created such as “sys.objects” and “sys.views” and were hailed as the “New and improved” versions of the original system tables. Also illusionary versions of the original system tables were created (views) in order to help to hide the system tables and to keep the DBAs and Users from screaming about backwards compatibility. The actual system tables were hidden and only the most experienced DBAs could find them and only when using special tools (DAC). And even then they could only be seen and not touched.

So when you go looking at the list of system views and you see sysobjects and sys.objects remember that once upon a time there was only the table sysobjects. And that the system view sysobjects will continue to haunt us until new code has stopped being written with it and it can be retired in peace.


Filed under: DBA Humor, Microsoft SQL Server, SQLServerPedia Syndication, System Functions and Stored Procedures Tagged: Humor, microsoft sql server, system functions, T-SQL

Does SQL Server do a CHECKDB during an instance restart?

$
0
0

When you start up an instance do you rely on the CHECKDB entry in the error log of SQL Server to tell if your databases are corrupt? You shouldn’t be.

Ever wonder why the CHECKDB can run so fast when you start up your instance but takes so long when you do it manually? Simple answer, it isn’t running at all. Here are the “CHECKDB” entries from my SQL 2012 instance that I just re-started.

2014-04-22 12:55:52.09 spid9s      CHECKDB for database 'model' finished without errors on 2014-04-19 10:08:18.273 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:52.92 spid16s     CHECKDB for database 'msdb' finished without errors on 2014-04-19 10:08:18.873 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.40 spid21s     CHECKDB for database 'DatabaseB' finished without errors on 2014-04-19 10:08:21.737 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.40 spid24s     CHECKDB for database 'TruncateTest' finished without errors on 2014-04-19 10:08:23.237 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.41 spid23s     CHECKDB for database 'ImpTest' finished without errors on 2014-04-19 10:08:22.813 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.41 spid19s     CHECKDB for database 'DatabaseA' finished without errors on 2014-04-19 10:08:21.207 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.41 spid18s     CHECKDB for database 'PartialyContained' finished without errors on 2014-04-19 10:08:20.957 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.41 spid17s     CHECKDB for database 'Tests' finished without errors on 2014-04-19 10:08:20.350 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.41 spid22s     CHECKDB for database 'DatabaseC' finished without errors on 2014-04-19 10:08:22.197 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:53.45 spid16s     CHECKDB for database 'CollationTest' finished without errors on 2014-04-19 10:08:23.743 (local time). This is an informational message only; no user action is required.
2014-04-22 12:55:54.27 spid24s     CHECKDB for database 'NewDBTest' finished without errors on 2014-04-19 10:08:24.500 (local time). This is an informational message only; no user action is required.

Note the restart date is 2014-04-22 12:55:52 but if you scan to the right you will see that the message says that CHECKDB finished without errors on 2014-04-19 10:08:18 several days earlier. As it happens I know that this is the last time I ran CHECKDB on these databases. The log is just displaying the results of the last time it was run.

So what does this mean for us? Primarily it means that after an instance has crashed (say someone tripped over the UPS cord) (no I’m not kidding) you should actually run DBCC CHECKDB on all of your databases rather than just relying on what’s in the log. This adds to your checkout time but potentially saves you a world of hurt if one of your DBs actually did turn up some corruption issues.


Filed under: DBCC, Log File, Microsoft SQL Server, SQLServerPedia Syndication, System Functions and Stored Procedures Tagged: DBCC, microsoft sql server, system functions

Granting or denying permissions to all of the tables within a database

$
0
0

When granting or denying permissions to the tables within a database you have two options. You can either add the user/role to one of the preexisting database roles

  • Db_datareader – grants SELECT to all tables & views in a database
  • Db_datawriter – grants INSERT, UPDATE and DELETE to all tables & views in a database
  • Db_denydatareader – denys SELECT to all tables & views in a database
  • Db_denydatawriter – denys INSERT, UPDATE and DELETE to all tables & views in a database

 
Or you can grant those permissions explicitly by granting/denying SELECT, INSERT, UPDATE and DELETE to the database itself. Unlike the roles you can also grant these permissions at the schema or even table/view level.

So what’s the difference? The code is obviously different but not really a big deal either way.

EXEC sp_addrolemember ‘db_datawriter’,’username’;  
	-- Add a user to a role
GRANT SELECT TO username; 
	-- Grant a permission to a user

In terms of access there is no real difference. A user granted SELECT on the database has exactly the same permission as one added to the db_datareader role.

The biggest difference in my experience is when you go to look at what permissions a user has. Role membership is found in sys.database_role_members and general permissions are found in sys.database_permissions.

In SSMS:

Roles:
TablePermissions1

Permissions:
TablePermissions2

Note that because I granted the permissions at the database level I have to look at the permissions tab on the database properties page not the securables tab on the user properties page. Had I granted the permissions at a lower level, say SELECT on the dbo schema, then I would have looked in the securables tab.

So which should you use? Really it doesn’t matter as long as you are consistent. My personal preference is to grant specific permission to roles then assign the roles to AD groups. The specific permissions because they are more granular and I can grant INSERT and UPDATE without granting DELETE, the roles make it easier to manage over the long run by giving you a single place with a logical name to grant a set of permissions. For example I can create roles that match a given position in the company. DBOperator1 and DBOperator2 for example. They may have almost identical permissions but DBOperator2 has the ability to do deletes or run some extra stored procedures. The AD groups is also an ease of management thing. My company has a “security team” that handles AD membership and checks to see if an individual is allowed to be in a given group. Since we already have people doing that work why should I want to add those tasks to my workload?

Remember the most important thing is to be consistent. If you have some users/groups in roles and others with direct permissions you are going to have a harder time down the road.


Filed under: Microsoft SQL Server, Security, SQLServerPedia Syndication, SSMS Tagged: database permissions, microsoft sql server, security, SSMS

Escaping from a runaway Logon trigger

$
0
0

Most people know that logon triggers can be dangerous if you aren’t careful. And if you didn’t know, well, logon triggers can be dangerous if you aren’t careful. They can be really useful and are a great tool, but if you mess up you can REALLY mess up.

If you install the following code (and don’t, just don’t)

USE master
GO
CREATE TRIGGER [Logon_Trigger] -- Trigger name
ON ALL SERVER FOR LOGON -- Tells you it's a logon trigger
AS
ROLLBACK; -- Kill the connection attempt
GO

You will end up with a situation where everyone sees the following message every time they try (unsuccessfully) to connect to your instance.

Logon_Trigger1

Now it may be nothing like that severe, you could end up only blocking all of your sysadmins or something like that.

So since there is always the possibility that something can go wrong what can we do to fix it?

First we need a connection. You can hope that you already have a connection open (maybe even the one that created the trigger in the first place). If so a logon trigger will not affect existing triggers so you should be good. If not then we need to open a connection using the DAC (dedicated admin connection). Logon triggers do not fire when connecting to the DAC so no triggers you create will block it. To connect to the DAC you can either use SQLCMD with the -A option or connect using a query window in SSMS. You cannot connect to the DAC using object explorer. In order to connect using a query window you will connect to ADMIN:ServerName\InstanceName. The “remote admin connections” setting will need to be set to 1 in order to connect from a remote machine. If it is not you will need to log into to the server directly and create your connection to the DAC from there.

Once you have the connection you need to know the name of the problem trigger. There are a couple of ways to do this. First if you wrote the trigger and know the name then you are golden. If not then you can run the following script:

SELECT * FROM sys.server_triggers
WHERE is_disabled = 0 -- If its a 1 it's already disabled 
				-- you don't care
  AND is_ms_shipped = 0 -- It was created by Microsoft you 
				-- don't care (hopefully)

This gives you a list of all of the server level triggers that are not already disabled and were not created by Microsoft. Now there may be triggers that are not logon triggers (server scoped DDL triggers for example) but are still server triggers. I’m honestly not sure how to tell the which are logon triggers and which are not without looking at the actual definition.

You can see the trigger definition by running this code:

SELECT [definition] FROM sys.server_sql_modules 
WHERE [definition] LIKE '%MyTestTrigger%'

Once you know the name(s) of the trigger(s) that are the problem you can do the following to disable/drop them.

You can then disable the trigger using the following command:

DISABLE TRIGGER [MyTestTrigger] ON ALL SERVER

Or drop it using this command:

DROP TRIGGER [MyTestTrigger] ON ALL SERVER

I HIGHLY recommend knowing how to stop a runaway logon trigger before implementing one. Otherwise you can get yourself into some trouble and the time to learn this stuff is not when your boss is standing over you because no one can log into the production box!


Filed under: Microsoft SQL Server, SQLServerPedia Syndication, SSMS, System Functions and Stored Procedures, T-SQL Tagged: code language, DAC, language sql, logon triggers, microsoft sql server, sql statements, sqlcmd, SSMS, system functions, T-SQL

DBA Myths: A table with a primary key is not a heap

$
0
0

Typically when you see a heading like this you know the answer is “No” or “False” but in this case it’s more of a “hu?” You see a primary key and a table being a heap have nothing to do with each other. Well very little anyway.

  • A “Primary Key” is a special case of a unique constraint (enforced by an index) that will not allow NULL values. There can be only one Primary Key.
  • A “Heap” on the other hand is a table without a clustered index.

 
Note the important terms here are “unique key” and “clustered index”. I should probably point out that a unique key/primary key can be clustered or non-clustered. Thus a table with a primary key can be a heap or not.

So why the confusion? Usually the default when you create a primary key is to create a unique clustered index to enforce it. Thus by default creating a primary key does in fact stop a table from being a heap. However you can override this (and in some cases clustered isn’t even the default) and create a non-clustered unique index to support the constraint. And a non-clustered primary key does not affect a table’s “heapness” (is that even a word?)


Filed under: Index, Microsoft SQL Server, SQLServerPedia Syndication Tagged: code language, index, language sql, microsoft sql server, T-SQL

Microsoft’s free virtual labs

$
0
0

If you have spent any time looking around my site, you will notice that I love study materials and in particular I love free ones. I even have a page devoted to study materials most of which are free.

Now Microsoft has dozens of virtual labs available on TechNet. That’s cool enough but did I mention they are free?!? I’ve talked about them before. A while back I mentioned a page by Zilckh who points out these labs and what types are available. (I’ll be adding a more direct link as well)

Over the last couple of weeks these labs have come up in conversation several times both on twitter and at my office. After all of that, I thought I would point them out, and of course if I’m going to point them out, I should probably give one a shot right?

So I decided to do the Upgrading to SQL Server 2012 from SQL 2005/2008 lab – this being a ongoing project at work. Now over the years, I’ve been involved in upgrades from 2000 to 2005 and 2005 to 2008 so I didn’t expect to see anything unfamiliar but I wanted to see how the labs themselves worked. I did run into some difficulty getting it started but mostly because of some security issues that I got taken care of pretty easily.

Once the lab started to load it brought up two separate windows.

  • The first was a manual for the lab. The manual had a general discussion on methods of doing the upgrade then walked you through testing the old server using the upgrade wizard and actually upgrading a couple of databases including making a couple of mistakes.
  • The other window was the lab itself. It had “links” to 3 different “machines”. One held the 2005 instance, another the 2012 instance, and to be honest I never needed the 3rd so I’m not sure what it was for.

The interface worked quite well and appeared to be full versions of SQL Server. At least when I made an unplanned mistake it reacted exactly like I would have expected it to. All in all it was a very positive experience and one I highly recommend. I look forward to trying out some of the others including the new SQL 2014 labs.


Filed under: Documentation, Microsoft SQL Server, SQLServerPedia Syndication Tagged: Documentation, microsoft sql server

Who has the DAC open?

$
0
0

The other day I started seeing the following error in my SQL log.

Error: 17810, Severity: 20, State: 2.

Could not connect because the maximum number of ’1′ dedicated administrator connections already exists. Before a new connection can be made, the existing dedicated administrator connection must be dropped, either by logging off or ending the process. [CLIENT: 127.0.0.1]

Now this disturbed me somewhat. It means that

  1. Someone is connected as the DAC
  2. The same someone or someone else is trying to connect to the DAC and failing

 
This connection is specifically for diagnostic queries when there are problems. It has a number of factors that make it “Not for general usage”. Including the facts that there can only be one of these connections at a time and it has it’s own (rather limited) resources. This means I need to track down who is connecting to the DAC or they may be connected to it when I actually need it. I’ll need to create an extended event session to track them down over time but for now I want to be able to tell who has a DAC connection open currently.

SELECT * 
FROM sys.dm_exec_sessions
WHERE endpoint_id = 1

The endpoint #1 is the DAC. You can see this in the system view sys.endpoints. Sys.dm_exec_sessions has a number of useful pieces of information that can lead us back to the culprit. Among others you will find the host (host_name), the application (program_name), the login (login_name) and the NT login if there is one (nt_domain and nt_user_name). This information is usually more than enough to find or at least start down the path of finding “who done it”.


Filed under: Microsoft SQL Server, Problem Resolution, SQLServerPedia Syndication Tagged: DAC, microsoft sql server, problem resolution

What is the difference between Money and Decimal(19,4)

$
0
0

One of my co-workers and I were discussing the difference between the data type MONEY and the data type DECIMAL(19,4). I was rather curious so I spent some time getting it all down on paper.

Details

First the obvious. MONEY takes up 8 bytes and stores the maximum possible values possible for the 8 bytes. 2^64 or -922,337,203,685,477.5808 to 922,337,203,685,477.5807. DECIMAL(19,4) will store any value that will fit into MONEY and then some, but it takes up 9 bytes. A DECIMAL(19,4) can hold a range of -999,999,999,999,999.9999 to 999,999,999,999,999.9999. This is actually considerably less than 2^72 (8bits * 9bytes) or -236,118,324,143,482,260.6848 to 236,118,324,143,482,260.6847 that actually could be stored in 9 bytes.
Next something interesting to try

CREATE TABLE MoneyTest (
	Mon1 money, Mon2 AS Mon1*Mon1, Mon3 AS Mon1*Mon1*Mon1,
	Dec1 decimal(19,4), Dec2 AS Dec1*Dec1, Dec3 AS Dec1*Dec1*Dec1,
	MonDec AS Mon1*Dec1, DecMon AS Dec1*Mon1);
GO
EXEC sp_help MoneyTest;
GO

With an output of

MoneyVsDecimal1

If you look at the Length, Precision and Scale you will notice that they change for any of the computed columns that use the DECIMAL column. This is because if you (for example) multiply a DECIMAL(4,2) times another DECIMAL(4,2) you end up with a DECIMAL(8,4). It stops at Precision 38 because that is the maximum size of a DECIMAL data type. The MONEY data type however does not change when multiplied by itself.

Summary
Size Min Max Precision
Money 8 -922,337,203,685,477.5808 922,337,203,685,477.5807 Static
Decimal(19,4) 9 -999,999,999,999,999.9999 999,999,999,999,999.9999 Changes
SmallMoney 4 -214,748.3648 214,748.3647 Fixed
Decimal(10,4) 9 -999,999.9999 999,999.9999 Changes

So the major difference is that Money data types are smaller but have a fixed size. Decimal on the other hand takes up more space and when multiplying the size, precision, and scale are going to change. Personally that means that I’m going to story invoice amounts (for example) as Money (or even SmallMoney where I can) and tax rate as a Decimal.


Filed under: Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, language sql, microsoft sql server, sql statements, T-SQL

15 years of experience with Identity columns

$
0
0
  • An identity column is an auto incrementing column
  • An identity column is typically used as a primary key
  • A primary key that’s an identity column is called a surrogate key
  • A surrogate key is one that is not related to the contents of the row in any way
  • An identity column must be NOT NULL
  • You can tell if a column is an identity column by looking at the is_identity column of sys.columns or using the COLUMNPROPERTY function (TableObjectId, ColumnName, ‘IsIdentity’)
  • An identity column has three parts. Data type, Seed, and Increment
  • The data type of an identity column is typically an INT but can be most numeric data types. ie tinyint, smallint, int, bigint, decimal(p,0), or numeric(p,0)
  • The seed defaults to 1 and is usually 1. It can however been any value that fits in the data type.
  • IDENT_SEED returns the original seed value of a table
  • To change the seed of a table use DBCC CHECKIDENT
  • The increment is how much the identity column increases each time a new row is added
  • If the increment is negative then the identity values do in fact go down
  • Negative increments can be handy if your identity column has reached the max value of the data type. Reseed to 0 (assuming that is where you started) and set your increment to -1.
  • IDENT_INCR returns the increment of a table
  • Identity columns can have gaps in the sequence
  • @@IDENTITY returns the last identity value generated within the current session but ignores scope
  • Don’t use @@IDENTITY unless you know you should
  • SCOPE_IDENTITY returns the last identity value generated within the current session and scope
  • SCOPE_CURRENT returns the last identity value generated for a specific table or view
  • Use SCOPE_IDENTITY when you want the identity value for the row you just inserted
  • Use SCOPE_CURRENT to get the most recent identity value from a table before you do an insert
  • Don’t use @@IDENTITY <- Worth repeating twice
  • To insert a row into a table with an identity column you must list the columns
  • In general you don’t list the identity column (the insert will fail even if there is a null value being inserted into the column)
  • If you want to insert a specific value into the identity column you have to use the IDENTITY_INSERT setting.
  • SET IDENTITY_INSERT TableName ON
  • Make sure you turn IDENTITY_INSERT back off when you are done. Only one table in a session can have IDENTITY_INSERT turned on at a time
  • SET IDENTITY_INSERT TableName OFF

Filed under: Microsoft SQL Server, SQLServerPedia Syndication, T-SQL Tagged: code language, language sql, microsoft sql server, sql statements, T-SQL

What is this default trace you speak of?

$
0
0

I frequently see the default trace mentioned in answers to forum questions, blog posts, articles, even training sessions. My knowledge of it after 15+ years with SQL Server unfortunately minimal. I know that it is a trace that is created by SQL automatically (hence the default) and that it is only so big and cycles the space. Not much right?

So let’s try to learn a bit more. First BOL. My search of BOL came up with “default trace enabled option

The default trace functionality provides a rich, persistent log of activity and changes primarily related to the configuration options.

It also appears that I’m a bit late to the party.

This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use Extended Events instead.

If you take a look back you will see the message first showed up in SQL 2012. It’s still around though so let’s continue a bit deeper.

You can read from the default trace using the fn_trace_gettable system table function.

SELECT * 
FROM fn_trace_gettable
('C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\LOG\log.trc', default);
GO

This is the query found in the link above and it assumes the default location of a default instance of 2014. You can confirm the actual location by using the sys.fn_trace_getinfo system table function. You can also assume that the traceid is 1 for the default trace although this isn’t necessarily the case.

SELECT *
FROM sys.fn_trace_getinfo(1); -- 0 or default to get the list of all traces
GO

Another (better) option is to look at the sys.traces system view. This has even more information and is just as easy to use.

SELECT *
FROM sys.traces
GO

DefaultTrace

I should note that I cut off the list of columns displayed. I’m only displaying those columns that I’m interested in for this post. First if you look at the is_default column you will see that this is in fact the default trace. Next if you look you will see that is_rollover is set to 1. This means that the trace will fill the existing file up to the max_size column (in this case 20mb) and then begin a new file. If it reaches the max_files (in this case 5) then it deletes the first file before starting the next. So the important thing here is that the default trace is a rolling 80-100mb. It is obviously meant to just tell us what has happend on the instance recently.

But what exactly is it going to tell us? Once we are sure what the traceid is we can see what events are used in the default trace using sys.fn_trace_geteventinfo. I’m not worried about which columns are being pulled so I’m going to do a SELECT DISTINCT eventid.

SELECT DISTINCT eventid
FROM sys.fn_trace_geteventinfo(1);
GO

This gives us a list of events which we can resolve using the information in the BOL entry for sys.sp_trace_setevent.

A couple of examples in the 2012 default trace include

Event Id
18 Audit Server Starts and Stops
20 Audit Login Failed
22 ErrorLog
46 Object:Created
47 Object:Deleted
55 Hash Warning

So now that we know the technical specs (or at least some of them), the question becomes “Why is there a default trace at all?” If you look you will notice that after an instance restart a new file is created and the first (if more than five is deleted). This leaves the previous 4 files intact. So if the server fails for some reason, if you are reasonably quick, you can take a look at some of what was going on before the crash. This can be very helpful during a postmortem.


Filed under: Microsoft SQL Server, SQLServerPedia Syndication, System Functions and Stored Procedures Tagged: default trace, microsoft sql server, system functions
Viewing all 450 articles
Browse latest View live