Linked Server errors connecting to SQL2k from SQL2k8

Today I was setting up a linked server from a SQL Server 2008 machine connecting to a SQL 2000 machine using SQLOLEDB. After configuring the server in 2008 I tested it on SQL 2008 machine and everything seemed to be running fine. When I tested out the linked server in SQL 2000 though I got the following errors:

The EXECUTE permission was denied on the object ‘xp_prop_oledb_provider’, database ‘mssqlsystemresource’, schema ‘sys’ . (Microsoft SQL Server, Error: 229) 

To fix this error I granted execute rights to the xp_prop_oledb_provider proc via the following script:

GRANT EXECUTE ON sys.xp_prop_oledb_provider TO [LOGIN]

After that I got the following error:

Message: Cannot obtain the schema rowset “DBSCHEMA_TABLES_INFO” for OLE DB provider “SQLNCLI10″ for linked server “[Linked Server Name]“.  The provider supports the interface, but returns a failure code when it is used.

To fix this error I found a Microsoft article that describes the needed steps to remedy

Unable to modify tables in SQL Server 2008

In Sql Server 2008, you may be unable to modify tables if they require a table rebuild.  The error you get is as follows:

Saving changes is not permitted.  The changes you have made require the following table to be dropped and re-created.  You have either made changes to a table that can’t be re-created or enabled the option Prevent saving changes that require the table to be recreated.

 

In order to get around this error you have to click Tools–>Options–>Designers and uncheck the check box for Prevent saving changes that require table re-creation.

 

Installing SQL Server 2008 on Windows 2008 R2

Today I was performing a new SQL Server 2008 install on a Windows 2008 R2 server.  I got 3 errors while performing the install and thought I would save everyone the trouble of searching the internet for all the workarounds so I included them all here.  The first error came when I tried installing the .Net framework via the SQL Setup.  It was not letting me install via the SQL install and I had to install the .Net framework in the features of the server management console.  You can do that by doing the following steps from this article

Where can I get the SQL Server 2008 sample databases?

Today I was reading over a really great article online.  One of the examples as you could guess was based on one of the SQL Server sample databases.  I really wanted to play around with it a bit but wouldn’t you know it?  I didn’t have the sample dbs installed anywhere.  I typically do not install the sample databases anymore as I always think they just take up space and I will never really use them.  Isn’t that always the case?  Well I went searching on the internet and I found them here on Codeplex and I figured I’d share the link with everyone.  You can download the SQL Server sample databases here.

SQLWebcast1 Part 3 of 3 from sqlworkshops.com

This is a webcast courtesy of SQLWorkshops.com 

Note: Doubleclick video for fullscreen.

In part 3 of this webcast Ramesh Meyyappan discusses how you can modify some queries to prevent sort spill overs to tempdb and he includes some tips you can use to do the same in certain situations.

[mediaplayer src='http://sqltechconsulting.com/video/SQLWebcast1Part3of3.wmv' autoLoad=1 ]

Running Large Serialized Transactions

I was loading  a very large amount of data into a test machine today.  I had the machine completely to myself, I had a backup before the process began and I had a profiler trace running on another machine to monitor every statement processed.  The load was all part of a serialized transaction.  The machine was running SQL Server 2005 Standard edition on a dual core server with 16GB of memory.  It’s not the best machine but for testing environment its more then competant.  So we have a pretty isolated environment and you would think everything should be pretty straight forward. 

Wouldn’t you know it?  Halfway through the 8 hour process, the machine became unresponsive on me.   I couldn’t connect via ssms, DAC, SQLCMD, nothing.  The machine was pegged at 100% CPU, the memory was at 100% as well.  The machine was basically shot and rolling down a hill.  The last statement I saw from my profiler was 20 minutes ago…just got back from lunch by the way, and oh boy….what a day this was working out to be.  And my boss just sent me an email asking how things were going.  I am going to explain how I went about solving this issue but I just want to let you know that this is not something that you can always do, but when in a bind and during certain conditions it is a pretty nifty solution and is why I thought it would make for an interesting article.  I was in a bind and I was trying to perform the action in the fastest possible time because people were waiting for the server, and they really needed to start doing their testing.  Here is what I did:

Since I was unable to connect to the SQL Server instance whatsoever, I had to do some drastic measures.  I had a backup and I was the only one on the server so I was not concerned with data loss.  So I just decided to kill the SQL Server service from the services control panel.  Wouldn’t you know it this hung on me too.   So being the cowboy I am, I just went to task manager and killed the sqlserver.exe while I was at it.  Now, knowing that this is a completely abrupt and unorthodox thing to do, I knew all the dbs were going to have to be recovered by SQL Server when the server was restarted.  I didn’t feel like waiting so I decided to do some more unorthodox things.  I renamed one of my datafiles on the database that I was working on.  Then I restarted the service.  This of course brings the db up, but in suspect mode.  From here you can just romove the suspect db and restore from a backup.  Again this is an unorthodox way, but it works in certain situations and mine was one of them. 

So now where does this leave me.  I had my database back to square one, the server was stable again, but I still have to run this monster data load that needs to be run and figure out just what happened to cause this whole mess.  All my DMV’s are also now useless as the service was restarted and do not contain any of the information I would have had if the darn server wasn’t unresponsive and I couldn’t connect to it.  I opened up the error log on windows only to find that it contains nothing to help me.  The SQL Server error log show’d nada as well.  I did have my profiler trace and I knew the last statement that completed so I tried running the statement it failed on.  No problems…so I started thinking and finally realized the issue. 

Well, I was running a serialized transaction, and because of this it has to keep the entire transaction of updates in memory until the final commit is issued.  When the machine ran out of phicical memory it started to thrash out to disk causing the server to become unresponsive and new connections were unable to connect.  So the moral of the story is to be sure that when you are running a serialized transaction that you have enough memory to hold the entire transaction.

How to install Security Policies for your SQL Servers

I just got back from another great meeting at my local SQL Server User Group. In tonight’s meeting we had a presenter named Joe Toscano.  Here’s some info about Joe the presenter:

Joe Toscano of RDA is a SQL Server Business Intelligence consultant, instructor and speaker based near Philadelphia, Pa. He has worked extensively with SQL Server since version 6.5, as well as Sybase and Informix prior to that. Joe’s areas of expertise include Data Transformation Services (DTS), Integration Services (SSIS), Transact-SQL (T-SQL) programming, data warehousing, performance tuning, replication, high availability (mirroring), security, disaster recovery, upgrading, migration projects and lights-out DBA tasks.

Joe was an absolutely wonderful presenter.  You can really see his passion and knowledge for databases by his expressions and demeanor throughout his entire presentation.  I was intrigued by his session from the beginning and he kept me extremely interested until the very end.  I thought the information I learned from him made for a great post so that’s why I am sharing that information with you all now.  So, Policy management.  What are they all about? 

Well Policy Management is a new feature in SQL Server 2008.  It allows you to define and enforce policies for configuring and managing SQL Server across the enterprise.  It requires setting up a Central Management Server (CMS) which acts as the traffic cop that monitors the other servers in your environment.  This CMS server must be SQL Server 2008, but it can monitor lower servers, like 2005 and 2000 etc.  When using the policies in 2008 and 2005, the policies actively prevent the conditions from occurring by issuing errors via ddl triggers.  With the servers pre 2005 they didn’t have this functionality yet so it is more of an after the fact implementation.  It’s still a great mechanism to keep track of those things none the less. 

So, before we can dive deeper into the subject and see some examples there are a number of terms that we need to define and understand regarding Policy-Based Management and those terms are:

  • Target - an entity that is managed by Policy-Based management; e.g. a database, a table, an index, etc.
  • Facet – a predefined set of properties that can be managed
  • Condition – a property expression that evaluates to True or False; i.e. the state of a Facet
  • Policy – a condition to be checked and/or enforced

I found this great step by step walkthrough with screenshots from Ray Barley on how to set up Policy-Based Management

How to Audit SSAS role permissions

A while back I was very disappointed to discover that SSAS does not have any easy way to go through all of your dimensions and cubes to see which users have access to which dimensions, cubes, etc.  Sure you can go one by one in order to get the information, but I was really just looking for an easy way to view the permissions based on individual object permissions, similar to the way you can in SSMS.  I called Microsoft and unbelievably they had no solution.  What a pinch to be in when you have an important audit coming and now it is going to take an absorbant amount of time to come up with the data the auditors are going to need.

Well, fortunately for me, I ran into an incredible site today.  It’s called ASSP – Analysis Services Stored Procedure Project This site is great!  It’s an open source project and it is just what the doctor ordered.  You can download the software and open up the project in Visual Studio.  From there you just build the ASSP assembly and you are all set.  This assembly has a number of various functions built into it and it returns a number of helpful datasets in the datasets you will be looking for.  They have also have additional reports and things pre-made and built right in to the project for you as well, so you can deploy those right to SSRS.  Here is an exerpt of one of the funtion calls and documentation:

DiscoverXmlMetaData(path, restrictions)
This function executes a DISCOVER_XML_METADATA command, which returns a hierarchical resultset and then “flattens” that resultset and returns it as a datatable which can be displayed by SSMS or used in a Reporting Services report.

Unfortunately standard Xpath style queries did not prove rich enough to return data in it’s full context. That is you could return a list of all the dimensions in every cube on a given server, but you could not return a column containing the cube and database to which they belonged. So a hybrid Xpath syntax was developed which allows you to specify a list of fields to return at each level.

The easiest way to explain this is with a few examples

In order to return return a list of all the dimensions in every cube in the current database you would issue the following command.

CALL ASSP.discoverXmlMetaData("DatabaseCubesCubeDimensionsDimension");

But this returns the list without any context, If you want to report the CubeName and LastProcessed date you would put a vertical bar (|) after the Cube element in the path and then put a comma separated list of fields that you want returned

CALL ASSP.discoverXmlMetaData("DatabaseCubesCube|Name,LastProcessedDimensionsDimension");

Note: it is not entirely true that the DiscoverXmlMetadata() command returns data without context – one of the features of this function is that it automatically returns the “ID” field of any ancestor elements in the resultset.

If you want to see what sort of paths are available the easiest way is to run the following command in an XMLA query window. You basically need to skip the xsd:schema> element and look at what is returned under the <row><xars:METADATA> elements.

<Discover xmlns="urn:schemas-microsoft-com:xml-analysis">
  <RequestType>DISCOVER_XML_METADATA</RequestType>
  <Restrictions />
  <Properties />
</Discover>

The path parameter actually matches from the leaf level up, so you could do a command like

CALL ASSP.discoverXmlMetaData("Dimension");

But this would produce a bit of a mess as it would return both cube dimensions and database dimensions and other dimension references from all over the xml resultset. The function is built in such a way that it build the columns for the resultset based off the first populated node in that matches the path so you will end up with a lot of blank columns.

But what this does mean is that you can specify just the minimal path that will unquiely identify the elements you are interested in.

eg

CALL ASSP.discoverXmlMetaData("CubeDimensionsDimension");

returns the same result as

CALL ASSP.discoverXmlMetaData("DatabaseCubesCubeDimensionsDimension");

It should be noted that because this is base on Xml, the path is case sensitive and “dimension” is not the same as “Dimension”.

Role information is not exposed by any of the other schema rowsets. The following commands will extract information about roles, dimension permissions, attribute permissions and cube permissions and would allow for the complete documentation of the security settings.

CALL ASSP.DiscoverXmlMetadata("DatabaseRolesRole");

CALL ASSP.DiscoverXmlMetadata("DatabaseDimensionsDimensionDimensionPermissionsDimensionPermission");

CALL ASSP.DiscoverXmlMetadata("DatabaseDimensionsDimensionDimensionPermissionsDimensionPermissionAttributePermissionsAttributePermission")

CALL ASSP.DiscoverXmlMetadata("DatabaseCubesCubeCubePermissionsCubePermission");

 

I am so thrilled!  This is just what I was looking for.  Check it out and see for yourselves just how great this assembly is.

Operand type clash: nvarchar(max) is incompatible with sql_variant

I received this error today while updating an extended property so I thought it would be a good little post to help others in the event that they come accross the same error as well.   Extended properties can be used for a great deal more then just for basic data dictionaries.  I’m currently working on a project where they are extensively using SMO for code generation and they store and engineer their systems information about the sql objects they generate on the extended properties of those sql objects.  While I was deploying a change today I got the following error

“Operand type clash: nvarchar(max) is incompatible with sql_variant ” 

This error seemed to have came about due to an upper size limit on the extended properties.   The default way of passing strings to the parameters in Unicode format as follows:

EXEC sys.sp_addextendedproperty
@name = N'MS_DescriptionExample',
@value = N'AdventureWorks Sample OLTP Database';

While this is pretty much how you will see all of the examples, you can convert the variant to pretty much any datatype you like except N)TEXT, IMAGE, TIMESTAMP and SQL_VARIANT.  Since the extended property I was using was passed as Unicode or NVARCHAR(MAX)  it was doubling the size and I ran into the 7,500 byte limit which was 3750 characters while in UNICODE.  To solve the error I  shrunk down the extended property to  a smaller character limit.    So if you get this type of error while working with extended properties take a look at your variables and rememebr that SQL converts them to Unicode which doubles the size of your strings and there is a limit of 7500 bytes.

What to do when a Rollback doesn’t rollback

I recently came across an article by Becky Sweger   that reminded me of a situation I experienced myself a while ago where a transaction did not rollback as planned.  This caused quite a surprise to me when I experienced it myself, so I thought I would write a small blog about it to help others as well.  Say for instance, that you have code that is issuing two or more dml statements  and they are grouped inside of a single transaction.  I will use Becky’s example here for simplicity sake:

 

BEGIN TRANSACTION

INSERT INTO dbo.Table1 (some COLUMNS)
VALUES (some VALUES)

SELECT @error = @@error, @rowcount = @@rowcount

IF @error <> 0
BEGIN ROLLBACK TRANSACTION RAISERROR('error on the first insert!', 16, 1) RETURN END

[DO STUFF]

INSERT INTO dbo.Table2 (some COLUMNS)
VALUES (some VALUES)

SELECT @error = @@error, @rowcount = @@rowcount

IF @error <> 0
BEGIN ROLLBACK TRANSACTION RAISERROR('error on the second insert!', 16, 1) RETURN END

COMMIT TRANSACTION

One would believe the error handling would be sufficient enough and the transaction would rollback when an error occurs.  While most of the time this is true, there are some occasions where it will not.  For instance, if there is a run-time error on the second statement, the first statement statement would not rollback.  Runtime errors could be anything from a renamed object to a devide by zero error etc.  You would be surprised how often this can happen. 

To prevent this from happening to you try to always include a SET XACT_ABORT to ON statement with all your transactions.  This will specify that the current transaction will automatically be rolled back in the event of a run-time error.

Beware, though, that even when XACT_ABORT is ON, not all errors terminate the batch. Here are the exceptions I know of:

  • Errors you raise yourself with RAISERROR.
  • Compilation errors (which normally terminate the scope) do not terminate the batch.
  • Error 266, Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing.

So at a minimum you still need to check @@error after the execution of a stored procedure or a block of dynamic SQL even if you use XACT_ABORT ON.