What I’d like to do in this article is to explain something about SQL Server extended properties, why they are so important, and illustrate some ways of working with them, scripting them, and maintaining them.
Why Extended Properties?Before SQL Server 2000, there was a very awkward problem with SQL Server: It was impossible to attach additional properties to a database object such as a database, schema, table, column, index or so on. Imagine that you wanted to attach a note to a database to provide the current version, and maybe list the previous deployments to bring this database up to the version. You couldn’t do it. These properties are important for documentation; particularly for tables and their associated properties such as columns and indexes because, in these cases, SQL Server doesn’t, and can’t, preserve the CREATE source with all its liberal comments and documentation.
There were then some ways around the problem, of course. Obviously, you could attach information about a database by creating a stored procedure or view to give you what amounted to global constants such as the version number, or the revisions that had taken place. This wouldn’t tackle other problems such as keeping the documentation about the table together with the table; the same applied to indexes, columns and other database objects where the objects source was not retained within the database. Then, as now, we also needed occasionally to attach additional information to columns to apply masks, application-validation information such as regexes, formatting information, caption information or other such things. Above all, it was documentation that was we needed. Then came extended properties.
Extended properties are easy to read, thanks to a useful system view. Sys.extended_properties . However, they are a pain to create, update and delete; they rely on special stored procedures that have a syntax that isn’t at all intuitive for those of us without mutant mental powers. They have a limit of 7,500 characters but are actually stored in a SQL_variant so that DateTime, Approximate numeric, exact numeric, character, Unicode and binary information can be stored in it. Most of us use some sort of tool such as SSMS to maintain this documentation rather than to do it via SQL. The SQL is cumbersome.
Extended Properties within SQL Server are complicated because of the way that SQL Server understands all the components/entities/things of a database. There is no single numeric identifier that will guarantee to uniquely identify a component of a database. Certainly, there is the object_ID of the system catalog views, but then only certain components are considered to be objects. Columns, for example, aren’t objects, and nor are indexes. Parameters aren’t either. Yet these are the very things that need documentation the most. SQL Server relies on a four-part dot-based identification system to reference any component. The name of each type is separated by dots. It will work fine, but because of the ‘uniqueness’ rules of SQL Server, you need to know what each component represents. This means that you also need a list of the types. The problem with this is that the names of database objects types aren’t consistent across the product and SSMS. In the catalog views, ‘Functions’ consist of several object types (TF, FN, IF, FS or FT) as can a ‘Procedure’ (P, PC, RF or X). The information schema catalog uses another different jargon. The diffeences in the terms used by SQL Server and SMO makes things more difficult. .
The four functions or procedures that allow you to maintain the extended properties, sys.fn_listextendedproperty, sp_addextendedproperty, sp_dropextendedproperty and sp_updateextendedproperty, aren’t easy to use. Although you can generally avoid the listing function, you can’t avoid the others easily. You don’t just provide the path to the entity/thing/component, but you have to parse both references into their component levels to provide the parameters to these procedures.
SMO grappled with this very problem and came up with a unique identifier, called the Uniform Resource Name(URN). This does the trick, though it complicates matters by using a subset of an XPath expression. It is a subset of an SMO query string that you can, I’m told, use in SMO to create collections of anything you specify that is an SMO object within the database. The difference is that the URN is a unique reference. With an easily serialised reference such as a URN, it is easy to get hold of a database ‘thing’ and document it by means of an extended property. Once you have any live SMO database object, you can assign a value to an existing extended property or create a new one using its ExtendedProperty value.
SMO has its own terms for the various classes of entities/things that it has in collections. You can easily get a list of them with this PowerShell code.
[enum]::GetValues([Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes])| foreach{"$_"}You will see that they are differences from the terms used by SQL Server
Editing and creating extended properties in PowerShell.If you have a serialized version of a unique URN reference to an object, then you have all that you need to instantiate a server object. (Microsoft.SqlServer.Management.SMO.Server) and made a connection with it. You then get any object you wish using the unique reference (URN).You can then read, or write to, any extended property for any component within any database on the server just by specifying Uniform Resource Name(URN) to the extended property of that object. So we can find the value of an MS_Description property on a view by …
($srv.GetSmoObject("Server[@Name='MyInstance']/Database[@Name='MyDatabase']/View[@Name='MyView' and @Schema='MySchema']/ExtendedProperty[@Name='MS_Description']")).Value…and you can change an existing value simply by assigning to it. You can create a new property perfectly easily. Here is a PowerShell function that does this for any SMO object.
<# .SYNOPSIS This either creates or alters an extended property on any database component (thing) .DESCRIPTION This uses SMO to check if a particular Extended property exists, and if it does it alters it to the value you supply, otherwise it creates the property with the value you provide .PARAMETER DatabaseObject The SMOobject that represents whatever you wish to attach or edit an extended property to. This is an object in the SMO sense, not the SQL Server sense. .PARAMETER Property The property (e.g. MS_Description) you wish to assign to, or whose value you wish to change. .PARAMETER NewValue The value you wish to assign to it .EXAMPLE $DatabaseName = 'Adventureworks2014' $Schema = 'Sales' $TableName = 'Currency' $Property = 'TestDescription' $NewValue='This is a wonderful table' $TheTable = $srv.Databases[$DatabaseName].Tables.Item($tableName, $Schema) if ((Edit-ExtendedProperty $TheTable $property $newvalue) -ne $TheTable.ExtendedProperties.item($Property).Value) {Write-Error 'Edit-ExtendedProperty failed'} .NOTES Over the years, different objects have been added to the pool of objects that are allowed to have properties. Now if you can think of it, you can probably attach an EP to it. Beware! the documentation is way out-of-date #> function Edit-ExtendedProperty { [OutputT