<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">John Magnabosco</title><subtitle type="html">SQL Server Development and Data Security</subtitle><id>http://www.simple-talk.com/community/blogs/johnm/atom.aspx</id><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/default.aspx" /><link rel="self" type="application/atom+xml" href="http://www.simple-talk.com/community/blogs/johnm/atom.aspx" /><generator uri="http://communityserver.org" version="2.0.60217.2664">Community Server</generator><updated>2009-07-01T10:24:00Z</updated><entry><title>Leadership for the DBA</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2010/01/23/88262.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2010/01/23/88262.aspx</id><published>2010-01-23T16:22:10Z</published><updated>2010-01-23T16:22:10Z</updated><content type="html">&lt;p&gt;Recently I read a book titled "&lt;a href="http://www.amazon.com/gp/product/0785289054/ref=s9_simi_gw_s0_p14_i1?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=center-2&amp;amp;pf_rd_r=0G9JEZAP9HZQNGGW5ADT&amp;amp;pf_rd_t=101&amp;amp;pf_rd_p=470938631&amp;amp;pf_rd_i=507846"&gt;The 21 Irrefutable Laws of Leadership&lt;/a&gt;" by &lt;a href="http://www.johnmaxwell.com/"&gt;John Maxwell&lt;/a&gt;. In this book, Maxwell categories the qualities that creates a great leader. As I read this book I thought about the many managers and leaders that I have encountered in my life, including the ones that we all have read about in the history books or seen on the evening news. I saw how these qualities were exhibited in some leaders and how they resulted in exceptional leadership. I also saw how these qualities were disregarded which resulted in disaster. &lt;/p&gt;  &lt;p&gt;The reading of this book would be incomplete without a fair share of introspection. I saw qualities that come to me naturally; but could use some refinement and intentional growth. I saw qualities in which I really struggle to be average. It was a great comfort to read in the book's introduction that even the author recognizes that he is weak in some of these qualities. It is also comforting to read that all of these qualities can be learned.&lt;/p&gt;  &lt;p&gt;As I concluded the reading of this book, I thought about the role of a DBA in light of these qualities. There are some DBAs, such as myself, who are in a role or position of leadership within their organization. There are other DBAs whose role is more of a solid technical one without any clear designation of leadership. One of the statements that Maxwell emphasizes in this book is that everyone has the opportunity for leadership even if their organizational position does not call for it. There is a clear difference between the mindset of leadership and positional leadership. The former can exist without the latter. The latter cannot be effective without the former.&lt;/p&gt;  &lt;p&gt;I would love to write about each of the 21 laws and how they relate to the DBA role; but it would be very likely that most reading this will not get past the first few before heading on to other blogs. There is only so much time in the day to read, right? So, for the benefit of brevity I will pull out two of these laws and provide some quick thoughts:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Law of the Lid:&lt;em&gt; "Leadership Ability Determines a Person's Level of Effectiveness"&lt;/em&gt;&lt;/strong&gt;    &lt;br /&gt;As a DBA you can possess all of the technical skills that can be acquired. You can take a poorly performing database and optimize the heck out of it. You can author the most effective and efficient T-SQL and speak to its minute intricacies. You can design an awesome database schema that is appropriately normalized and indexed. All of this can make you very effective technically; but if you cannot express your thoughts in a way that the non-technical managers of your organization can understand and be convinced to fund your efforts financially or resources you will not realize your full effectiveness. &lt;/p&gt;  &lt;p&gt;A DBA who has put as much effort into refining their leadership skills as they have their technical skills will flow into the category of being an exceptional DBA. &lt;a href="http://www.bradmcgehee.com/"&gt;Brad McGehee&lt;/a&gt; has often spoken and written about "&lt;a href="http://www.slideshare.net/markginnebaugh/brad-mcgehee-become-an-exceptional-dba-march-2009"&gt;How to become an exceptional DBA&lt;/a&gt;". Many of the qualities that he speaks of are a great representation of the balance of technical skills and leadership qualities.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Law of Connection: &lt;em&gt;"Leaders Touch a Heart Before They Ask for a Hand"&lt;/em&gt;&lt;/strong&gt;    &lt;br /&gt;The DBA role is often characterized as a fascist dictator who guards the database realm with a pack of rabid Doberman Pincers. He carries a big stick and uses it quickly leaving Developers cowering in the corner paralyzed. This certainly is not the picture of an exceptional DBA with leadership skills.&lt;/p&gt;  &lt;p&gt;An exceptional DBA with leadership skills will make the effort to understand the task that the Developer has been charged with and take the time to discuss solution options. When the DBA can elevate the skills and morale of the Developers then they are exhibiting leadership qualities. When the DBA is busy tearing down the Developers they are a destructive element. Think about how you speak of the Developers that you work with when you are conversing with other DBAs.&lt;/p&gt;  &lt;p&gt;Imagine the culture that I described at the beginning of this section where the DBA and Developers are infected with the "&lt;em&gt;us vs. them&lt;/em&gt;" spirit. What will the response be when the DBA is in need of the Developer's assistance? Would the DBA even approach them for help? How effective will the DBA be in their role? &lt;/p&gt;  &lt;p&gt;&lt;em&gt;"Leaders define reality."&lt;/em&gt; - John Maxwell    &lt;br /&gt;&lt;em&gt;"Be the change you want to see in the world."&lt;/em&gt; - Mahatma Gandhi&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=88262" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Comparing WHERE and FROM Filtering</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2010/01/04/85333.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2010/01/04/85333.aspx</id><published>2010-01-04T11:47:28Z</published><updated>2010-01-04T11:47:28Z</updated><content type="html">&lt;p&gt;&lt;em&gt;&lt;font color="#000080"&gt;I am kicking off the new year with a quick jaunt back in time through Mr. Peabody's &lt;/font&gt;&lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/WABAC_machine"&gt;&lt;em&gt;&lt;font color="#000080"&gt;WABAC Machine&lt;/font&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;font color="#000080"&gt;. The blog entry below was published on April 30, 2008, during my pre-Simple-Talk blogging days. The topic below is something that I have found to be a valuable consideration in optimizing queries. Enjoy!&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;As we work with other Professionals in our industry, we quickly learn that there are many ways to accomplish a given task. When presented with multiple options in a situation, there are times where one option stands out as the optimal choice based upon our general knowledge of the database engine. &lt;/p&gt;  &lt;p&gt;There are also times where the optimal choice may not be so obvious and will vary depending on many considerations such as database architecture, level of use, indexing, hardware configuration or general best practices. Any given approach may perform superbly with one database and drag on another.&lt;/p&gt;  &lt;p&gt;A sample case might be that we are given two versions of a seemingly simple query that filters the data. One option is the common use of a &lt;strong&gt;WHERE&lt;/strong&gt; clause. The other is utilizing the filters within the &lt;strong&gt;JOIN&lt;/strong&gt; clause. The examples below illustrate the syntax differences between these options.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;WHERE Filter Option     &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#004000" face="Courier New"&gt;SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TABLE1].[FIELD1]        &lt;br /&gt;FROM        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TABLE1]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; INNER JOIN [TABLE2]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON [TABLE1].[FIELD1] = [TABLE2].[FIELD1]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; INNER JOIN [TABLE3]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ON [TABLE2].[FIELD2] = [TABLE3].[FIELD2]        &lt;br /&gt;WHERE        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TABLE1].[FIELD1] = 700        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND [TABLE2].[FIELD2] &amp;gt; 1000        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND [TABLE3].[FIELD2] &amp;gt; 1000&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;JOIN Filter Option&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#004000" face="Courier New"&gt;SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TABLE1].[FIELD1]        &lt;br /&gt;FROM        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TABLE1]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; INNER JOIN [TABLE2]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON [TABLE1].[FIELD1] = [TABLE2].[FIELD1]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND [TABLE1].[FIELD1] = 700        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND [TABLE2].[FIELD2] &amp;gt; 1000         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; INNER JOIN [TABLE3]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON [TABLE2].[FIELD2] = [TABLE3].[FIELD2]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND [TABLE3].[FIELD2] &amp;gt; 1000&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;When these are executed, the Query Optimizer evaluates the query and determines the best execution plan for the statement. In this case, Query Optimizer determined that both options should utilize the same execution plan; but since these statements are syntactically unique they are cached separately.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Execution Plan&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#004000" face="Courier New"&gt;Nested Loops(Inner Join)       &lt;br /&gt;|--Nested Loops(Inner Join, OUTER REFERENCES:([TABLE2].[FIELD2]) WITH PREFETCH)| |--Clustered Index Seek(OBJECT:([TABLE2].[TABLE2_P]),SEEK:([TABLE2].[FIELD1]=700 AND [TABLE2].[FIELD2] &amp;gt; 1000) ORDERED FORWARD)| |--Clustered Index Seek(OBJECT:([TABLE3].[TABLE3_P]), SEEK:([TABLE3].[FIELD2]=[TABLE2].[FIELD2]), WHERE:([TABLE3].[FIELD2]&amp;gt;1000) ORDERED FORWARD)        &lt;br /&gt;|--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([TABLE1]))        &lt;br /&gt;|--Index Seek(OBJECT:([TABLE1].[IX_TABLE1_2]), SEEK:([TABLE1].[FIELD1]=700) ORDERED FORWARD)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In review of SQL Server Profiler, the duration of the T-SQL batch appear identical (both reflected the value of 20 in my sample). A review of the &lt;a href="http://msdn.microsoft.com/en-us/library/ms179881.aspx"&gt;sysprocesses&lt;/a&gt; system table reveals some interesting information about these two options. The CPU, Physical IO (Reads) and Memory usage are significantly different.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;strong&gt;JOIN Option&lt;/strong&gt;    &lt;br /&gt;CPU: 200    &lt;br /&gt;PIO: 5    &lt;br /&gt;MEM: 15&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;WHERE Option&lt;/strong&gt;    &lt;br /&gt;CPU: 19110    &lt;br /&gt;PIO: 707    &lt;br /&gt;MEM: 38&lt;/p&gt;  &lt;p&gt;According to this information, the performance of the filtering that occurred within the &lt;strong&gt;JOIN&lt;/strong&gt; clause performed much better than the &lt;strong&gt;WHERE&lt;/strong&gt; clause option. To ensure that the initial differences in the performance was not unique to the first execution, I ran the same queries multiple times, obtaining a cache hit for each execution. The results were consistent. &lt;/p&gt;  &lt;p&gt;It is important to note that these numbers and results are specific to my test environment. The results reflected in your specific environment may differ; but through the sample above the process of evaluating and selecting the most optimal solution is illustrated.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=85333" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>NCDM Conference</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/12/13/79359.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/12/13/79359.aspx</id><published>2009-12-13T22:16:31Z</published><updated>2009-12-13T22:16:31Z</updated><content type="html">&lt;p&gt;Last week I jetted of to Las Vegas, Nevada with my co-workers to attend the &lt;a href="http://www.eiseverywhere.com/ehome/index.php?eventid=6433&amp;amp;tabid=2572"&gt;National Center for Database Marketing&lt;/a&gt; (NCDM) Conference. This conference was not like the conferences that we as database professionals typically attend. Rather than offering sessions about database maintenance, performance and design the offerings were focused on its use by Marketing Analysts and how it can be used more effectively to manage their campaigns.&lt;/p&gt;  &lt;p&gt;At first I was not sure how much I would get out of the conference since it was focused in an area to which I was unfamiliar; but as I attended each session I learned how my customers in the Marketing Department use data. I learned about their needs. I learned about the questions that they ask when they approach data. I saw how the tools and methods that I have offered in the past, while currently effective, could be improved. I saw opportunities for me to anticipate their needs when provisioning data for their analysis. &lt;/p&gt;  &lt;p&gt;I learned some of the marketing-speak so that I can better understand the requests that come my way. In the Marketing world the term "Business Intelligence" is referred to as "Customer Intelligence". The term "Marketing Database" is their portion of the "Data Warehouse" that stores data that is important to the Marketing Analyst. Understanding these terms and concepts will aid me in building a Business Intelligence solution for the company. &lt;/p&gt;  &lt;p&gt;At the NCDM Conference, I purchased a book titled "&lt;a href="http://www.amazon.com/Strategic-Database-Marketing-Masterplan-Customer-Based/dp/007145750X/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1260742397&amp;amp;sr=8-1"&gt;Strategic Database Marketing&lt;/a&gt;" authored by Arthur Hughes. This book further discusses the terms and concepts that were presented at the NCDM Conference. I look forward to reading it and gaining a better understanding of the data needs of those that my technical services support.&lt;/p&gt;  &lt;p&gt;There were many sessions that discussed the phenomenon of social media and how marketing efforts can take advantage of it. It was interesting to see not only how &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt;, &lt;a href="http://www.facebook.com"&gt;Facebook&lt;/a&gt; and blogging can be leveraged in a Marketing campaign; but also see how these tools can utilized as a data source for analysis. These sessions were presented not from people who are theorizing about how these can be used; but from Marketers who have successfully leveraged social media in their campaigns.&lt;/p&gt;  &lt;p&gt;As I boarded the plane back to Indianapolis I reflected on my experience at the NCDM Conference. While there were some sessions that were better than others, it was a very positive and worthwhile experience. I am thankful that I had the opportunity to attend. I would encourage all database professionals to seek to understand data from the perspective of their customers. Attending conferences such as NCDM go a long way in that effort. Compliment your technical education with the understanding of the business that you support. It makes you a well-rounded and effective IT professional.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=79359" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Shades of Schemas</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/11/21/77591.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/11/21/77591.aspx</id><published>2009-11-21T17:22:31Z</published><updated>2009-11-21T17:22:31Z</updated><content type="html">&lt;p&gt;I am sure that some of the database nomenclature that is used might be a bit confusing to those who are entering into the wonderful world of SQL Server. An example would be the varying use of the word "schema". &lt;/p&gt;  &lt;p&gt;In a &lt;strong&gt;general database terms&lt;/strong&gt; a schema is the organization and definition of the tables within a database, their relationship to one another and the columns that are contained within them. In layman's terms: it is the design of the database. &lt;/p&gt;  &lt;p&gt;In &lt;strong&gt;SQL Server 2000&lt;/strong&gt;, the term "schema" was directly associated with &lt;a href="http://msdn.microsoft.com/en-us/library/aa905163(SQL.80).aspx"&gt;ownership of database objects&lt;/a&gt; (tables, views, stored procedures, etc.), which is a slight deviation from the aforementioned definition. The ownership of database objects is important because the object owner (user or role) is implicitly granted all privileges to the object. If the ownership is not explicitly defined when the object is created, the default owner is the same as the database owner; which is defined by the "dbo" default schema.&lt;/p&gt;  &lt;p&gt;In many ways, the difference between users and ownership schemas were synonymous in SQL Server 2000. With the release of &lt;strong&gt;SQL Server 2005&lt;/strong&gt;, the &lt;a href="http://msdn.microsoft.com/en-us/library/ms189462(SQL.90).aspx"&gt;database object schema&lt;/a&gt; provided a new definition of a "schema". In this case a schema is a physical database object which serves as a logical grouping of database objects. For the .NET Developer, it is very similar to the concept of &lt;a href="http://msdn.microsoft.com/en-us/library/0d941h9d.aspx"&gt;namespaces&lt;/a&gt;. While the ownership aspect still remains it has been &lt;a href="http://msdn.microsoft.com/en-us/library/ms190387(SQL.90).aspx"&gt;separated from the principal&lt;/a&gt; in a such a way that it is much more flexible and scalable. &lt;/p&gt;  &lt;p&gt;Database object schemas are a great addition to SQL Server and in many ways is more consistent with the original definition of a schema than it's SQL Server 2000 counterpart.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=77591" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Sensitive Data in Memory</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/11/06/76068.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/11/06/76068.aspx</id><published>2009-11-06T11:52:36Z</published><updated>2009-11-06T11:52:36Z</updated><content type="html">&lt;p&gt;SQL Server offers many cryptographic methods such as one-way encryption (hashing) and cell-level encryption. These methods all are designed to protect data while it is stored in the database. To utilize encrypted data it must be decrypted. In doing so, the formerly protected sensitive data is captured into the process memory in plain text. &lt;/p&gt;  &lt;p&gt;Below is an example of a value, "ThisIsPlaintext", that is stored in the database using cell-level encryption and appears in plain text in the process memory after querying:&lt;/p&gt;  &lt;p&gt;&lt;font color="#800000" size="2" face="Courier"&gt;'s e l e c t&amp;#160; t h e&amp;#160; w h o l e&amp;#160; r o w . . 0 ' ' ' ' . . . 0      &lt;br /&gt;' ' ' . . . . ' ' ' ' ' 0 . ' . . ' ' 3 . * . &lt;strong&gt;T h i s I s        &lt;br /&gt;P l a i n t e x t&lt;/strong&gt; . . . . . . . . . . . . . . . . . . . . . &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;With the &lt;a href="http://technet.microsoft.com/en-us/library/ms174415.aspx" target="_blank"&gt;HashBytes&lt;/a&gt; method, decryption does not occur. Instead, a value is hashed and the resulting hash is compared to the stored hashed value. If there is a match, then it is confirmed that the correct value was compared. When the HashBytes method is executed, it requires the sensitive data to be passed as a parameter in plain text. It is at this point that the plain text value is captured into the process memory. The text below illustrates this occurrence in the process memory: &lt;/p&gt;  &lt;p&gt;&lt;font color="#800000" size="2" face="Courier"&gt;s e l e c t . . . C A S E&amp;#160; W H E N C i p h e r _ T e x t      &lt;br /&gt;= H a s h B y t e s ( ' S H A 1 ', ' &lt;strong&gt;M y&amp;#160; S e n s i t i v e        &lt;br /&gt;V a l u e&lt;/strong&gt; ' ) T H E N&amp;#160; ' T r u e ' E L S E ' F a l s e '       &lt;br /&gt;E N D . . . f r o m . . . d b o . H a s h b y t e s _ S a m&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;A similar occurrence can be seen when a user gains access to SQL Server through a SQL Server Login. The authentication process is very similar to the HashBytes method in that it does not perform decryption of the stored password, instead it creates a hash value of the password that was submitted and compares it to the hash value that is stored in the database. When a positive match occurs authentication is granted and the submitted password is stored in plain text as a part of a connection string in the process memory, as illustrated below:&lt;/p&gt;  &lt;p&gt;&lt;font color="#800000" size="2" face="Courier"&gt;S Q L _ _ _ _ _ _ P r o c e s s _ _ _ _ _ _ &lt;font color="#800000" size="2" face="Courier"&gt;A v a i l a b l e &lt;/font&gt;.       &lt;br /&gt;. . ' ' ' . - . s e r v e r = ' M y S e r v e r '; u i d = '       &lt;br /&gt;T e s t L o g i n ' ; p a s s w o r d = ' &lt;strong&gt;T h i s i s m y p a        &lt;br /&gt;s s w o r d&lt;/strong&gt; ' ; A p p l i c a t i o n&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;font color="#008000"&gt;&lt;strong&gt;TIP:&lt;/strong&gt; Utilize &lt;/font&gt;&lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb402886.aspx" target="_blank"&gt;&lt;em&gt;&lt;font color="#008000"&gt;Windows Authentication&lt;/font&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;font color="#008000"&gt; instead of SQL Server Logins to grant access to a SQL Server instance. Windows Authentication does not store passwords in plain text in the process memory.&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;At first glance this vulnerability may seem quite alarming; but it is not one that is unmitigated. To view the process memory in a Microsoft Windows operating system requires administrative privileges to the server. If a hacker, or malicious individual, were to gain this level of privileges to the server there is very little they cannot do. One of which is to disable or uninstall any &lt;a href="http://www.sentrigo.com/passwords"&gt;software&lt;/a&gt; that was installed on the server to protect the process memory. Additionally, the ability to read the process memory is the least of your concerns if a hacker had gained this level of control over your server.&lt;/p&gt;  &lt;p&gt;The exposure of sensitive data in the process memory is not unique to the Microsoft world of products. There are methods in Oracle that require plain text arguments, such as &lt;a href="http://www.red-database-security.com/whitepaper/oracle_passwords.html" target="_blank"&gt;ALTER USER&lt;/a&gt;, which result in the sensitive values to be cached. The decryption process in Oracle also results in plain text values being stored in memory. Other operating systems, such as Unix, also reveal sensitive data in its process memory. &lt;/p&gt;  &lt;p&gt;The protection methods that are available in SQL Server are designed to protect data while it is stored in the database. Once it is queried and cached there is a dependency upon the operating system of the server as well as the application performing the query to provide additional layers of protection. In this example, the restricted access to the process memory is managed by the operating system. &lt;/p&gt;  &lt;p&gt;There is no magic bullet that one application can provide that mitigates all possible vulnerabilities. It is the security methods of all components, including the people factor, working in concert and in layers that achieves a secure environment.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=76068" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Louisville SQL Saturday</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/25/75803.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/25/75803.aspx</id><published>2009-10-25T21:41:23Z</published><updated>2009-10-25T21:41:23Z</updated><content type="html">&lt;p&gt;It was early morning on Saturday, October 24th when some of my friends and I piled into my Jeep, with coffee in hand, for an enjoyable road trip from Indy to the Louisville SQL Saturday event. Enroute we all enjoyed great conversations ranging from the pros and cons of virtualization to the upcoming Colts football game.&lt;/p&gt;  &lt;p&gt;Upon arrival we signed in and began our day of learning and fellowship. There were two tracks available for the SQL hungry: The Database Administration track and the Business Intelligence track. With a fresh cup of Joe in my hand I proceeded to attend the Database Administration track. The following sessions were the ones that I attended:&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;Demystifying Transact-SQL&lt;/strong&gt; by Jason Follas    &lt;br /&gt;This session was a very good "back to the basics" session on T-SQL. It is always good to revisit the basics no matter how advanced you are in any discipline. Coverage of UNION/UNION ALL would have been a valuable addition to the presentation; but time was certainly a restriction.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;The XML Capabilities of SQL Server 2008&lt;/strong&gt; by Jason Follas    &lt;br /&gt;This session was also very good. It covered the XML data type and the functionality that is available in using this data type. It was good to hear more details about this powerful feature.    &lt;br /&gt;    &lt;br /&gt;- &lt;strong&gt;Comparing Clustering Methods&lt;/strong&gt; by Alex Prusakov    &lt;br /&gt;This session was presented at &lt;a href="http://www.indypass.org/Home/tabid/61/language/en-US/Default.aspx"&gt;IndyPASS&lt;/a&gt; back in March, 2009. While the March presentation was very good I felt that this version was even more interesting. This presentation solidified my understanding of clustering and how I may approach this need in my own environment.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;SQL Server Consolidation and Virtualization&lt;/strong&gt; by Sarah Barela and Ryan Jones    &lt;br /&gt;This session was a perfect follow-up to the topic presented by Alex. The tag team approach to the presentation was an interesting approach. At the end I was not sure that I had much to take with me and apply to my world; but there was some good questions presented by the audience.    &lt;br /&gt;    &lt;br /&gt;- &lt;strong&gt;Powershell in SQL Server 2008&lt;/strong&gt; by Arie Jones    &lt;br /&gt;This session was presented at &lt;a href="http://www.indypass.org/Home/tabid/61/language/en-US/Default.aspx"&gt;IndyPASS&lt;/a&gt; back in November, 2008. This session was fast paced. The power of this feature was successfully demonstrated. The challenge with this feature is that it requires some hands-on to fully grasp its scope. Arie's energy kept the audience going as the day was heading for a close.&lt;/p&gt;  &lt;p&gt;In addition to attending the above sessions I engaged into some great discussions with the event organizer and &lt;a href="http://louisville.sqlpass.org/"&gt;Louisville PASS Chapter&lt;/a&gt; leader, Malathi Mahadevan. She successfully organized a quality event. One in which many in attendance look forward to a sequel in the near future. I am also very pleased to see the &lt;a href="http://www.sqlsaturday.com/events.aspx?returnurl=eventhome.aspx"&gt;SQL Saturday&lt;/a&gt; events begin to be popping-up in the mid-west.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=75803" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Less Than Desirable Reads</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/14/75331.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/14/75331.aspx</id><published>2009-10-14T10:44:53Z</published><updated>2009-10-14T10:44:53Z</updated><content type="html">&lt;p&gt;&lt;em&gt;&lt;font color="#000080"&gt;Once again, firing up Mr. Peabody's&lt;/font&gt; &lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/WABAC_machine"&gt;&lt;em&gt;WABAC Machine&lt;/em&gt;&lt;/a&gt;&lt;em&gt; &lt;font color="#000080"&gt;unearthed a valuable blog entry that I posted before my Simple-Talk blogging days. The post below was originally published on March 2008 and maintains its relevance. Enjoy!&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I was watching a very interesting &lt;a href="http://www.imdb.com/title/tt0259711/"&gt;movie&lt;/a&gt; quite a few months ago. In this movie, the primary character hopped into his sports car in the middle of the day, backed out of his driveway and proceeded to travel down a deserted street in the middle of New York City. I have never visited the "Big Apple" but I would suspect that this occurrence would be quite an anomaly.&lt;/p&gt;  &lt;p&gt;It would be reasonable to assume that having only a singular transaction occur within a SQL Server database would be an equivalent anomaly to the one presented in the movie previously mentioned. To this, the delicate balance between data concurrency and data consistency begins.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms173763.aspx"&gt;Transaction isolation level&lt;/a&gt; in stored procedures is the traffic cop on the street of transactions. They prevent those nasty collisions that backup the flow of data. While a detailed description of all transaction isolation levels is another blog entry, I wanted to explore the Evil-Read Trio that can occur if careful consideration of these transaction isolation levels does not occur.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;THE DIRTY READ&lt;/strong&gt;: These are not the ones that are found in the foot locker of your neighborhood teenager. These are transactions that read uncommitted data modifications that are made by another transaction. This can wreak havoc if aggregated calculations occur while transactions are being added or modified and especially of these modifications are rolled back. Using the READ COMMITTED isolation level will prevent the occurrences of dirty reads.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;THE NON-REPEATABLE READ&lt;/strong&gt;: Complex stored procedures may execute a SELECT statement more than once within the same transaction. If another transaction modifies the data prior to the completion of the first transaction different results may occur when the second occurrence of the SELECT statement is run. The utilization of REPEATABLE READ isolation level will prevent the occurrences of non-repeatable reads as well as dirty reads.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;THE PHANTOM READ&lt;/strong&gt;: Much like a non-repeatable read, this type of read depends upon a multiple execution of a SELECT statement within the same transaction and another transaction modifying the data in which the SELECT statement is querying. In the case of the phantom read the modification of the data is an INSERT or DELETE which causes the row in question to appear and/or disappear within the reading transaction. While &lt;a href="http://www.imdb.com/title/tt0087332/"&gt;Ghostbusters&lt;/a&gt; may not have a good solution for this, the use of SERIALIZABLE READ isolation level will prevent phantom reads as well as non-repeatable and dirty reads.&lt;/p&gt;  &lt;p&gt;The question may arise to how it can be determined that these types of reads are occurring. The ol' handy-dandy &lt;a href="http://msdn.microsoft.com/en-us/library/ms187929.aspx"&gt;SQL Server Profiler&lt;/a&gt; can be employed to expose these reads. Include the &lt;a href="http://msdn.microsoft.com/en-us/library/ms190242.aspx"&gt;SQL:StmtStarting&lt;/a&gt; , &lt;a href="http://msdn.microsoft.com/en-us/library/ms189886.aspx"&gt;SQL:StmtCompleted&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms190441.aspx"&gt;SQL:BatchStarting&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/ms176010.aspx"&gt;SQL:BatchCompleted&lt;/a&gt; event classes in    &lt;br /&gt;the trace to catch the occurrence.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=75331" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>SQL Server MVP</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/10/75269.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/10/10/75269.aspx</id><published>2009-10-10T20:05:15Z</published><updated>2009-10-10T20:05:15Z</updated><content type="html">&lt;p&gt; On July 13th I received an e-mail that stated "&lt;em&gt;I wanted to let you know that you have been nominated&amp;#160; for an MVP award for your exceptional contribution to the Microsoft technical community&lt;/em&gt;!". I was thrilled with this prospect; but knowing that there are likely thousands of candidates across the globe that are nominated each quarter I was prepared to be happy with just the nomination. &lt;/p&gt;  &lt;p&gt;It was late on October 1st when I arrived at home from my day of work. After dinner, I migrated into the family room and began my nightly routine of catching up with the daily chat on &lt;a href="http://www.facebook.com"&gt;Facebook&lt;/a&gt; and &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt;. Upon checking my e-mail I saw e-mail from &lt;a href="http://mvp.support.microsoft.com/default.aspx"&gt;Microsoft&lt;/a&gt; that read, "&lt;em&gt;Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award!&lt;/em&gt;". the rest of the evening is a blur.&lt;/p&gt;  &lt;p&gt;The next morning, I gave &lt;a href="http://blogs.msdn.com/jimmymay/default.aspx" target="_blank"&gt;Jimmy May&lt;/a&gt;, my buddy who nominated me for the award, a phone call to inform him of the good news. In his admirably enthusiastic manner he exclaimed "&lt;em&gt;Way to go El Magnifico!&lt;/em&gt;", which is his long time nickname for me. I was on cloud nine.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;In my conversation with Jimmy, he asked me what would I do with my MVP status. I replied with "&lt;em&gt;Keep doing what I'm doing&lt;/em&gt;." My participation and contribution to the technical community was not driven by the passion to receive the award; but rather the passion to share knowledge and to aid in the building of a strong technical community that has a collaborative spirit and is accessible to all who are interested. That has not changed with this honor.&lt;/p&gt;  &lt;p&gt;Another question that has been asked of me lately is how to become a Microsoft MVP. There is no such thing as a check list of things to accomplish which results in the MVP designation. My answer to this question is to participate in the technical community, find your passion and be its advocate.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=75269" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Strong Password Generator</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/30/75042.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/30/75042.aspx</id><published>2009-09-30T10:21:56Z</published><updated>2009-09-30T10:21:56Z</updated><content type="html">&lt;p&gt;Frank, the DBA, has been asked to create a series of passwords that will be used to protect a collection of symmetric keys. These keys will in turn be used to protect some sensitive data in a database. &lt;/p&gt;  &lt;p&gt;Frank knows that the expectation is that these passwords will need to be strong passwords. Using the names of his cat's new born litter will not suffice. He made that mistake at his last job. Reviewing his notes to remind himself of the definition of a strong password he identifies the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1) The length of the password must be 8 characters or greater.      &lt;br /&gt;2) Does not include a series of letters that make a word or phrase.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; For example: "Password", "BettyIsHot", "FrankRocks".       &lt;br /&gt;3) The series of passwords that will be created are not sequential.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; For example:&amp;#160; "Password1", "Password2", "Password3".       &lt;br /&gt;4) Contains a variety of characters including uppercase letters, lowercase letters,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; numeric values and special characters.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;With a sigh, Frank makes his first attempt at his series of passwords. It wasn't long until his human nature creped in and his so-called random series of characters didn't appear as random they should be. The injection of significant dates (08131969, 12071941 and 05291453), his favorite bands (U2, UB40 and B52s) and pseudo-words (M0V31T, &lt;a href="mailto:R4d1c@L"&gt;R4d1c@L&lt;/a&gt; and P@sSw0rd) kept sneaking in.&lt;/p&gt;  &lt;p&gt;After a few minutes of contemplation, a bag of beef jerky and a bottle of &lt;a href="http://www.yoo-hoo.com/" target="_blank"&gt;Yoo-Hoo&lt;/a&gt;, inspiration descended upon Frank like a &lt;a href="http://en.wikipedia.org/wiki/Nude_Descending_a_Staircase,_No._2" target="_blank"&gt;Marcel Duchamp&lt;/a&gt; painting. He opened Management Studio and began typing furiously. The result was the following T-SQL script that assembles a series of characters in a loop that ultimately produces a strong password:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#008000"&gt;&lt;strong&gt;-- Variables&lt;/strong&gt;         &lt;br /&gt;DECLARE @PassLen int;&amp;#160; &lt;br /&gt;DECLARE @Pass varchar(50);         &lt;br /&gt;DECLARE @LoopCt int;         &lt;br /&gt;DECLARE @Rnd int;         &lt;br /&gt;        &lt;br /&gt;&lt;/font&gt;&lt;font color="#008000"&gt;&lt;strong&gt;-- Password length          &lt;br /&gt;&lt;/strong&gt;SET @PassLen = 10;         &lt;br /&gt;&lt;strong&gt;-- Starting value of password          &lt;br /&gt;&lt;/strong&gt;SET @Pass = '';         &lt;br /&gt;&lt;strong&gt;-- Starting value of loop&lt;/strong&gt;         &lt;br /&gt;SET @LoopCt = 1;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#008000"&gt;&lt;strong&gt;-- Loop to generate the password&amp;#160; &lt;br /&gt;&lt;/strong&gt;WHILE @LoopCt &amp;lt;= @PassLen         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; BEGIN         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- Generate a random number to select a character&lt;/strong&gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SET @Rnd = Convert(int,(1 + RAND() * (9-1))); &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- Build the password using the selected character          &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SELECT @Pass = @Pass +         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CASE&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- This option is weighted&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WHEN @Rnd &amp;gt;=1 AND @Rnd &amp;lt;=3 THEN         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- a-z&lt;/strong&gt;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHAR(Convert(int,(97 + RAND() * (122-97))))         &lt;br /&gt;&lt;/font&gt;&lt;font color="#008000"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; -- This option is weighted          &lt;br /&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WHEN @Rnd &amp;gt;=4 AND @Rnd &amp;lt;=6 THEN        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- A-Z&lt;/strong&gt;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHAR(Convert(int,(65 + RAND() * (90-65))))         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WHEN @Rnd = 7 THEN         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- 0-9&lt;/strong&gt;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHAR(Convert(int,(48 + RAND() * (57-48))))         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- #$%&amp;amp; (Special Character)          &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHAR(Convert(int,(35 + RAND() * (38-35))))         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; END         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;-- Advance the loop &lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SET @LoopCt = @LoopCt + 1;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; END&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#008000"&gt;&lt;strong&gt;-- Return the password          &lt;br /&gt;&lt;/strong&gt;SELECT @Pass;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#008000"&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In his code, Frank thought it wise to weight the uppercase and lowercase letters so that they would be selected more often than the numeric and special character to prevent the occurrence of passwords that look like "1234567%9#", "#$%&amp;amp;%$#%$1". A sampling of the passwords that Frank generated through this code are: DqOC0bPkqF, Q3t6%mQk%l, UAFdK%gvvq and Rrs#qm%#f$.&lt;/p&gt;  &lt;p&gt;After a few executions of this code Frank completed his task at hand. He handed his list of generated passwords to Betty, the Junior DBA, to implement. The data was once again safe. Betty was happy to no longer see Frank's lame flirting attempts through passwords like "W1llUg02th3M0v1eZw1thM3?".&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=75042" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Protecting SQL Server Data</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/12/74809.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/12/74809.aspx</id><published>2009-09-12T17:51:35Z</published><updated>2009-09-12T17:51:35Z</updated><content type="html">&lt;p&gt;It was late in 2008 and I had been blogging for over a year in my dusty corner of the Internet on various SQL Server topics when an opportunity arose to move my blog to &lt;a href="http://www.simple-talk.com/community/blogs/johnm/default.aspx" target="_blank"&gt;Simple-Talk.com&lt;/a&gt;. With this opportunity I decided to focus my blog topic to security of sensitive data which had become a passion of mine. Through this opportunity another was born: to author a book.&lt;/p&gt;  &lt;p&gt;Writing a book, technical or otherwise, has been a bucket-list (items to do before I "kick the bucket") item of mine for as long as I can remember. I have attempted to begin the process on various topics throughout the years. Some attempts we no more than an idea scribbled on a napkin; others actually got as far as a first draft of an introduction. There was even a failed attempt to author a fiction novel that would be something similar to the stories written by &lt;a href="http://en.wikipedia.org/wiki/Dashiell_Hammett" target="_blank"&gt;Dashiell Hammett&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;It was early 2009. My latest attempt of fleshing out of a book idea was an outline on the subject of securing sensitive data. This outline had been periodically molded and reshaped over the past year. It was beginning to look somewhat interesting. So much so, I began to seek some advice from other authors in regard to the publishing process. It was through a conversation with &lt;a href="http://www.simple-talk.com/community/blogs/brad_mcgehee/default.aspx" target="_blank"&gt;Brad McGehee&lt;/a&gt; in which I expressed an interest in authoring a book. I mentioned my outline to him and he encouraged me to contact &lt;a href="http://www.simple-talk.com/books/" target="_blank"&gt;Simple-Talk Publishing&lt;/a&gt; to see if they would be interested in pursuing it. To my surprise they were very interested!&lt;/p&gt;  &lt;p&gt;With the encouragement from my editor, &lt;a href="http://www.simple-talk.com/community/blogs/tony_davis/default.aspx" target="_blank"&gt;Tony Davis&lt;/a&gt;, and valuable feedback from &lt;a href="http://www.sqlservercentral.com/blogs/brian_kelley/default.aspx" target="_blank"&gt;Brian Kelley&lt;/a&gt; the outline was finalized and the writing process began. Over the next six months I spent many hours in the evening and on the weekends researching, writing, scripting and revising. There were times where the sentences flowed like water; other times like molasses. There were chapters submitted for first draft review that were completely re-written on the second draft. There were chapters that were spawned from other chapters and the book was re-organized a time or two. I thoroughly enjoyed the entire process.&lt;/p&gt;  &lt;p&gt;There were a few versions of the title for my book. Originally, it was the overly lengthy "&lt;em&gt;A Pocket Guide to Protecting Sensitive Data in SQL Server&lt;/em&gt;". Later it was shortened to "&lt;em&gt;Protecting Sensitive Data in SQL Server&lt;/em&gt;". Some early notifications of my book listed this version of the title. Finally, the search-optimized and more concise "&lt;strong&gt;Protecting SQL Server Data&lt;/strong&gt;" was selected as the final version of the title. &lt;/p&gt;  &lt;p&gt;&lt;a title="Protecting SQL Server Data" href="http://www.simple-talk.com/RedGateBooks/JohnMagnabosco/protecting_sensitive_data_in_sql.htm" target="_blank"&gt;&lt;img align="left" src="http://www.simple-talk.com/iwritefor/articlefiles/784-Magnabosco_cover_large.jpg" width="105" height="135" /&gt;&lt;/a&gt;There were a few concepts tossed to-and-fro for the image that would be presented on the cover of the book. Simple-Talk Publishing uses a general theme of images of gates which is a play off of their affiliation with &lt;a href="http://www.red-gate.com/" target="_blank"&gt;Red Gate Software&lt;/a&gt;. An early suggestion that I provided was the ironic image of a man locking a gate while getting pick-pocketed. The wisdom of the artists at Simple-Talk Publishing presented an alternate option of a gate at the &lt;a href="http://www.ouls.ox.ac.uk/bodley" target="_blank"&gt;Bodleian Library&lt;/a&gt; at the University of Oxford. It was an image that was complimentary to the topic. The image to the left is the final cover for my book. It is one in which I am very pleased.&lt;/p&gt;  &lt;p&gt;On &lt;strong&gt;September 21, 2009&lt;/strong&gt; an &lt;a href="http://www.sqlservercentral.com/articles/books/68066/" target="_blank"&gt;eBook&lt;/a&gt; version of my book will become available for download. Shortly afterwards a hardcopy version on my book will be available at &lt;a href="http://www.amazon.com/" target="_blank"&gt;Amazon.com&lt;/a&gt; for purchase. It is my hope that you enjoy reading this book as much as I did writing it.&lt;/p&gt;  &lt;p&gt;Below is the list of chapters for my book &lt;em&gt;&lt;strong&gt;Protecting SQL Server Data&lt;/strong&gt;&lt;/em&gt;:&lt;/p&gt;  &lt;p&gt;Chapter 1: Understanding Sensitive Data   &lt;br /&gt;Chapter 2: Data Classification and Roles    &lt;br /&gt;Chapter 3: Schema Architecture Strategies    &lt;br /&gt;Chapter 4: Encryption Basics for SQL Server    &lt;br /&gt;Chapter 5: Cell-level Encryption    &lt;br /&gt;Chapter 6: Transparent Data Encryption    &lt;br /&gt;Chapter 7: One-way Encryption    &lt;br /&gt;Chapter 8: Obfuscation    &lt;br /&gt;Chapter 9: Honeycombing a Database    &lt;br /&gt;Chapter 10: Layering Solutions&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=74809" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Let's Do The Time Warp</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/02/74635.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/09/02/74635.aspx</id><published>2009-09-03T02:24:27Z</published><updated>2009-09-03T02:24:27Z</updated><content type="html">&lt;p&gt;Back in November of 2008, I blogged on the topic of &lt;a href="http://www.simple-talk.com/community/blogs/johnm/archive/2008/11/07/70387.aspx"&gt;Transparent Data Encryption (TDE) and its affects on the tempdb&lt;/a&gt; database. Within that post I mentioned that the tempdb is dropped and recreated when the instance of SQL Server is restarted. Through the process of restarting an instance and reviewing the tempdb and its accompanying database encryption key, an anomaly was discovered. Here is the scenario:&lt;/p&gt;  &lt;p&gt;On an instance of SQL Server that contained a database that had TDE enabled, I stopped the instance by right-clicking on the instance within SQL Server Management Studio (SSMS) and clicked on the "stop" option. Once the instance stopped, I started it again by right-clicking the instance and clicked the "start" option.&lt;/p&gt;  &lt;p&gt;I queried the &lt;a href="http://msdn.microsoft.com/en-us/library/ms178534.aspx"&gt;sys.databases&lt;/a&gt; catalog view to reveal the create date of my tempdb:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#008000"&gt;SELECT        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; name,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create_date         &lt;br /&gt;FROM&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sys.databases        &lt;br /&gt;WHERE         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; name = 'tempdb';&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The results of this query revealed that the current version of the tempdb was created on:    &lt;br /&gt;&lt;strong&gt;2009-09-01 21:16:26.623&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I then queried the &lt;a href="http://msdn.microsoft.com/en-us/library/bb677274.aspx"&gt;sys.dm_database_encryption_keys&lt;/a&gt; dynamic management view (DMV) for the database encryption key that is used to protect the tempdb database:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#008000"&gt;SELECT        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; database_id,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create_date         &lt;br /&gt;FROM         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sys.dm_database_encryption_keys         &lt;br /&gt;WHERE         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; database_id = 2;&lt;/font&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The results of this query revealed that the current version of the tempdb database encryption key was created on: &lt;strong&gt;2009-09-02 01:16:18.583&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;At first glance, the difference in the date might give appeared to contradict the understanding that the database encryption key is recreated as the tempdb is recreated during an instance restart; but with closer inspection I noticed that the create date of the encryption key is in the future!&lt;/p&gt;  &lt;p&gt;I thought to myself "&lt;em&gt;It's astounding. Time is fleeting. How could this be&lt;/em&gt;?"&amp;#160; &lt;br /&gt;My recent encounter of converting my time zone, &lt;a href="http://en.wikipedia.org/wiki/Eastern_Time_Zone"&gt;Eastern Standard Time&lt;/a&gt; (EST), to &lt;a href="http://en.wikipedia.org/wiki/GMT"&gt;Greenwich Mean Time&lt;/a&gt; (GMT) revealed that this five hour difference was familiar.&lt;/p&gt;  &lt;p&gt;With a jump to the left, and a step to the right, this baffling time warp was cracked. The sys.databases catalog view reflects the time based off of the time zone that has been defined on your server, in my case EST, while the sys.dm_database_encryption_keys DMV utilizes GMT; therefore, the understanding is confirmed: the tempdb database encryption key is recreated along with the recreation of the tempdb database when the instance is restarted.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=74635" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Varchar and NVarchar</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/08/21/74477.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/08/21/74477.aspx</id><published>2009-08-21T10:31:17Z</published><updated>2009-08-21T10:31:17Z</updated><content type="html">&lt;p&gt;&lt;em&gt;&lt;font color="#000080"&gt;Another trip with Mr. Peabody's &lt;/font&gt;&lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/WABAC_machine"&gt;&lt;em&gt;&lt;font color="#000080"&gt;WABAC Machine&lt;/font&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;font color="#000080"&gt; unearthed a valuable blog entry that I posted before my Simple-Talk blogging days. This one is somewhat of a "Back to the basics" style blog entry that I thought would be worth sharing once again. Enjoy!&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;If you peruse quotes and philosophies of very successful people it will not take long to see that revisiting the basics of a discipline is something that is critical to excelling; thus, I thought that it would be a good idea to comment on the&lt;strong&gt; varchar&lt;/strong&gt; and &lt;strong&gt;nvarchar&lt;/strong&gt; data types.&lt;/p&gt;  &lt;p&gt;According to SQL Server 2005 Books Online the varchar(n) data type is described as:   &lt;br /&gt;&lt;em&gt;"Variable-length, non-Unicode character data. n can be a value from 1 through 8,000."&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;According to SQL Server 2005 Books Online the nvarchar(n) data type is described as:   &lt;br /&gt;&lt;em&gt;"Variable-length Unicode character data. n can be a value from 1 through 4,000."&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The "n" referred to above is the defined maximum size of the data type. For example declaring the column in your table as varchar(50) will mean that the column will store up to 50 characters. For the untrained eye the immediate impression may be that varchar can store twice the data of nvarchar. In actuality both data types store the same number of bytes - it is the number of characters that differ. Within the BOL definitions above the key word to pay attention to is "Unicode".&lt;/p&gt;  &lt;p&gt;Non-Unicode characters are stored in a single byte. For example: "A" would be encoded as an ASCII value of "65". These single byte values range from 0 - 255 which are represented in an ASCII table. The following link is a good resource for these values: &lt;a href="http://www.asciitable.com/"&gt;http://www.asciitable.com/&lt;/a&gt;    &lt;br /&gt;    &lt;br /&gt;In reviewing the ASCII table you will find that if you are using languages that utilize characters that are not included in the ASCII table (such as Japanese, Chinese, Korean, etc.) it can be rather limiting. &lt;/p&gt;  &lt;p&gt;Unicode characters are encoded in two bytes (double-byte). For example: "A" would be stored as a value of "A". These double-byte characters have 65,536 combinations which accommodates majority, if not all, languages in the world. A good tool to convert ASCII text to Unicode text can be found at this link: &lt;a href="http://www.industrialtrainer.com/Unicode.shtm"&gt;http://www.industrialtrainer.com/Unicode.shtm&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If the database that is being designed does not need to consider character sets beyond the ASCII set the use of varchar would be the more efficient storage option; but in this world of ever growing globalization and need to accommodate various character sets it may be wise to consider the strategic utilization of nvarchar for select columns.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=74477" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Random Numeric Variance</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/29/74188.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/29/74188.aspx</id><published>2009-07-29T10:57:41Z</published><updated>2009-07-29T10:57:41Z</updated><content type="html">&lt;p&gt;In the efforts of preventing unauthorized access to sensitive data, scrambling production data for testing, staging and development environments is a recommended practice. There are many ways to approach data scrambling. One option for numeric values is a process called "numeric variance".&lt;/p&gt;  &lt;p&gt;Numeric variance is a process in which the actual numeric values contained within a specified column are increased or decreased by a given percentage. For example, an original value of a bank account balance for a customer is $500. With a numeric variance of 10% applied, the new value for the account balance will be changed to $550. &lt;/p&gt;  &lt;p&gt;The addition of a randomizer will strengthen the results of the numeric variance. This strength is that each row of the affected column will be increased or decreased by a different percentage than the other rows. &lt;/p&gt;  &lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/ms177610.aspx"&gt;RAND&lt;/a&gt; function can be utilized to generate a random number. By leaving out the seed argument, SQL Server will dynamically determine the seed that will be used. If a hard-coded value is entered into the seed argument the value returned will be the same for each execution.&lt;/p&gt;  &lt;p&gt;Below is some sample code that can be used to perform a randomized numeric variance:&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Set original value      &lt;br /&gt;DECLARE @OrigVal int       &lt;br /&gt;SET @OrigVal = 500&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Set variance to 10%      &lt;br /&gt;DECLARE @VarPct numeric (5,2)       &lt;br /&gt;SET @VarPct = 10&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The preceding code simply provides us with variables to store our original value ($500) and our maximum variance percentage (10%). This process can be created either as a stored procedure or a user defined function; if created as such, these can be used arguments.&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Set number range for random number      &lt;br /&gt;DECLARE @Range int       &lt;br /&gt;SET @Range = (((0-@VarPct)+1)-@VarPct)&lt;/font&gt;&lt;font color="#008000"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Set random element      &lt;br /&gt;DECLARE @Rand int       &lt;br /&gt;SET @Rand = CONVERT(int,(@Range * RAND() + @VarPct)) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The preceding code uses the RAND function to create a randomized value. When you attempt to create a user-defined function with RAND function contained within it you will receive the following error:&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;Msg 443, Level 16, State 1, Procedure &amp;lt;UDF NAME&amp;gt;, Line &amp;lt;LOCATION OF RAND&amp;gt;     &lt;br /&gt;Invalid use of a side-effecting operator 'rand' within a function.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;A work around this issue is to create a simple view that can be referenced to obtain the RAND value. In our specific example, the resulting @Rand variable will contain the value of -19. This value represents the range from -9% to 10%, including 0%.&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Determine numeric variance      &lt;br /&gt;DECLARE @Variance int       &lt;br /&gt;SET @Variance = CONVERT(INT,((@OrigVal*@Rand)/100))&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;-- Return new value      &lt;br /&gt;SELECT @OrigVal + @Variance       &lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The preceding code uses our randomized value and generates a new variance with each execution. For illustration purposes let's say that the @Variance value returned is 35. This value is then added to our original value to change 500 to 535. If @Variance returned -45 the adding of a negative number is the same as subtracting a positive number; therefore 500 + -45 = 455.&lt;/p&gt;  &lt;p&gt;This process is repeated for each row. At the end, our result is a successfully scrambled set of numeric values that protects the sensitive data that is contained within these columns.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=74188" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Storage Allocation for NULL</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/10/73992.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/10/73992.aspx</id><published>2009-07-10T15:12:00Z</published><updated>2009-07-10T15:12:00Z</updated><content type="html">&lt;p&gt;A friend of mine approached me the other day and asked a great question: "W&lt;em&gt;hen a NULL value is stored in a varchar data type, how much memory is allocated in its storage.&lt;/em&gt;" My friend, being of the scientific mind that he is, then added "...&lt;em&gt;and how can I verify it&lt;/em&gt;."&lt;/p&gt;  &lt;p&gt;The slice of pepperoni pizza in my hand provided a great device to allow a pause to contemplate a response without giving the impression that I did not know the answer to his question. Unfortunately, the bite that I took was not sufficient because I was still working on my response when I was done chewing. I defaulted to the response of "&lt;em&gt;Alex, that is a great question&lt;/em&gt;." and politely promised that I would research the answer and get back to him.&lt;/p&gt;  &lt;p&gt;The following is the results of my research and the test I used to verify my answer:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Sample Tables      &lt;br /&gt;&lt;/strong&gt;For our test, we will create two simplified tables that contains a single column and three records. The difference between these tables is the data type that is used for our column:     &lt;br /&gt;    &lt;br /&gt;&lt;font color="#008040"&gt;-- Uses the CHAR data type      &lt;br /&gt;CREATE TABLE MyCharTest (testCol CHAR(10) NULL);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- Uses the VARCHAR data type      &lt;br /&gt;CREATE TABLE MyVarCharTest (testCol VARCHAR(10) NULL);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The data that will be used in our test will be three values: "1234567890", "" and NULL. For later reference, we will make note of the physical sizes of these values through the &lt;a href="http://msdn.microsoft.com/en-us/library/ms173486.aspx"&gt;DATALENGTH&lt;/a&gt; method. This provides us a measurement without the influence of the data type in which they are stored.     &lt;br /&gt;&lt;font color="#008040"&gt;     &lt;br /&gt;SELECT DATALENGTH('1234567890');       &lt;br /&gt;-- Returns a value of 10 bytes       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;     &lt;br /&gt;SELECT DATALENGTH('');       &lt;br /&gt;-- Returns a value of 0 bytes       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;     &lt;br /&gt;SELECT DATALENGTH(NULL);       &lt;br /&gt;-- Returns a value of NULL&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The final preparation for our sample tables is to populate the with our values:&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- Inserts into MyCharTest table      &lt;br /&gt;INSERT INTO MyCharTest (testCol) VALUES ('1234567890');       &lt;br /&gt;INSERT INTO MyCharTest (testCol) VALUES ('');       &lt;br /&gt;INSERT INTO MyCharTest (testCol) VALUES (NULL);       &lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- Inserts into MyVarCharTest table      &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;INSERT INTO MyVarCharTest (testCol) VALUES ('1234567890');      &lt;br /&gt;INSERT INTO MyVarCharTest (testCol) VALUES ('');       &lt;br /&gt;INSERT INTO MyVarCharTest (testCol) VALUES (NULL);       &lt;br /&gt;GO&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Test Script&lt;/strong&gt;     &lt;br /&gt;The following is a script to obtain a page dump of a given table. This script uses &lt;a href="http://msdn.microsoft.com/en-us/library/aa258281(SQL.80).aspx"&gt;DBCC&lt;/a&gt; statements to obtain the page dump information. Prior to executing the script below, replace the @DB and @TBL variables with the name of your database (@DB) and table (@TBL) that you are evaluating. Also, set the output of the script to be presented in text (In the menu bar of Management Studio, click on: Query. Results To. Results To Text); otherwise the DBCC PAGE information will not be presented.&lt;/p&gt;  &lt;p&gt;We will execute this script once for our MyCharTest table and a second time for our MyVarCharTest table: &lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;USE MyDatabase; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- variables to make the script flexible      &lt;br /&gt;    DECLARE @DB varchar(50);       &lt;br /&gt;    DECLARE @TBL varchar(50);       &lt;br /&gt;    SET @DB = 'MyDatabase';       &lt;br /&gt;    SET @TBL = 'MyCharTest';   &lt;/font&gt;&lt;font color="#008000"&gt;&lt;em&gt;--&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- enables the specified trace      &lt;br /&gt;-- 3604 is trace flag output is returned to the application       &lt;br /&gt;    DBCC TRACEON(3604); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;-- create table variable to capture DBCC IND results      &lt;br /&gt;    DECLARE @Ind TABLE (       &lt;br /&gt;                    PageFID  tinyint, PagePID int, IAMFID tinyint, IAMPID  int,       &lt;br /&gt;                    ObjectID  int, IndexID tinyint, PartitionNumber tinyint,       &lt;br /&gt;                    PartitionID bigint, iam_chain_type  varchar(30), PageType tinyint,       &lt;br /&gt;                    IndexLevel tinyint, NextPageFID tinyint, NextPagePID int,       &lt;br /&gt;                    PrevPageFID tinyint, PrevPagePID int       &lt;br /&gt;                    );       &lt;br /&gt;    -- execute DBCC IND and capture in @Ind temp table       &lt;br /&gt;    INSERT INTO @Ind EXEC('DBCC IND(' + @DB + ', ' + @TBL + ', -1);');       &lt;br /&gt;    -- snag the PagePID from the @Ind temp table       &lt;br /&gt;    DECLARE @PagePID int;       &lt;br /&gt;    SELECT @PagePID = PagePID       &lt;br /&gt;        FROM @Ind       &lt;br /&gt;        WHERE PageType = 1 and PrevPageFID = 0 and PrevPagePID = 0; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#008040"&gt;    -- execute DBCC PAGE to see the memory dump      &lt;br /&gt;    DBCC PAGE (@DB, 1, @PagePID, 3)    &lt;br /&gt;    -- disables the specified trace.       &lt;br /&gt;    DBCC TRACEOFF(3604);       &lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The CHAR Test      &lt;br /&gt;&lt;/strong&gt;The first execution of the script above is against our MyCharTest sample table that contains a column data type of &lt;a href="http://msdn.microsoft.com/en-us/library/ms187323.aspx"&gt;CHAR&lt;/a&gt;(10). The results were:&lt;/p&gt;  &lt;p&gt;For the first row, containing the value "1234567890", the page dump appears as follows:  &lt;br /&gt;&lt;font color="#008040"&gt;Slot 0, Offset 0x60, Length 17&lt;/font&gt;&lt;font color="#008040"&gt;      &lt;br /&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP     &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 17        &lt;br /&gt;&lt;/font&gt;Memory Dump @0x6198C060       &lt;br /&gt;00000000:   10000e00 31323334 35363738 39300100 ?&lt;/font&gt;&lt;font color="#008040"&gt;&lt;font color="#ff0000"&gt;....1234567890..        &lt;br /&gt;&lt;/font&gt;00000010:   00???????????????????????????????????&lt;font color="#ff0000"&gt;.&lt;/font&gt;     &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;Slot 0 Column 1 Offset 0x4 Length 10 &lt;/font&gt;&lt;font color="#ff8000"&gt;Length (physical) 10&lt;/font&gt;        &lt;/p&gt;  &lt;p&gt;For the second row, containing the value "", the page dump appears as follows:    &lt;br /&gt;&lt;font color="#008040"&gt;Slot 1, Offset 0x71, Length 17      &lt;br /&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP     &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 17        &lt;br /&gt;&lt;/font&gt;Memory Dump @0x6198C071       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;00000000:   10000e00 20202020 20202020 20200100 ?&lt;font color="#ff0000"&gt;....          ..        &lt;br /&gt;&lt;/font&gt;00000010:   00???????????????????????????????????&lt;/font&gt;&lt;font color="#ff0000"&gt;.&lt;/font&gt;                        &lt;br /&gt;&lt;font color="#008040"&gt;Slot 1 Column 1 Offset 0x4 Length 10 &lt;/font&gt;&lt;font color="#ff8000"&gt;Length (physical) 10&lt;/font&gt;        &lt;/p&gt;  &lt;p&gt;For the third row, containing the NULL value, the page dump appears as follows:    &lt;br /&gt;&lt;font color="#008040"&gt;Slot 2, Offset 0x82, Length 17      &lt;br /&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP     &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 17        &lt;br /&gt;&lt;/font&gt;Memory Dump @0x6198C082       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;00000000:   10000e00 88e18308 00000000 00000100 ?&lt;font color="#ff0000"&gt;.....á.........        &lt;br /&gt;&lt;/font&gt;00000010:   01???????????????????????????????????&lt;/font&gt;&lt;font color="#ff0000"&gt;.&lt;/font&gt;                        &lt;br /&gt;&lt;font color="#008040"&gt;Slot 2 Column 1 Offset 0x0 Length 0 &lt;/font&gt;&lt;font color="#ff8000"&gt;Length (physical) 0&lt;/font&gt;        &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The VARCHAR Test      &lt;br /&gt;&lt;/strong&gt;The second execution of the script above is against our MyVarCharTest sample table that contains a column data type of &lt;a href="http://msdn.microsoft.com/en-us/library/ms175005.aspx"&gt;VARCHAR&lt;/a&gt;(10). The results were:&lt;/p&gt;  &lt;p&gt;For the first row, containing the value "1234567890", the page dump appears as follows:    &lt;br /&gt;&lt;font color="#008040"&gt;Slot 0, Offset 0x60  Length 21      &lt;br /&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS       &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 21&lt;/font&gt;       &lt;br /&gt;Memory Dump @0x61EEC060       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;00000000:   30000400 01000001 00150031 32333435 ?&lt;font color="#ff0000"&gt;0..........12345&lt;/font&gt;       &lt;br /&gt;00000010:   36373839 30??????????????????????????&lt;/font&gt;&lt;font color="#ff0000"&gt;67890&lt;/font&gt;          &lt;br /&gt;&lt;font color="#008040"&gt;Slot 0 Column 1 Offset 0xb Length 10 &lt;font color="#ff0000"&gt;&lt;font color="#ff8000"&gt;Length (physical) 10&lt;/font&gt;  &lt;/font&gt;&lt;/font&gt;       &lt;/p&gt;  &lt;p&gt;For the second row, containing the value "", the page dump appears as follows:    &lt;br /&gt;&lt;font color="#008040"&gt;Slot 1, Offset 0x75, Length 9      &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP     &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 9&lt;/font&gt;       &lt;br /&gt;Memory Dump @0x61EEC075       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;00000000:   10000400 01000000 00?????????????????&lt;/font&gt;&lt;font color="#ff0000"&gt;.........&lt;/font&gt;                &lt;br /&gt;&lt;font color="#008040"&gt;Slot 1 Column 1 Offset 0x0 Length 0&lt;/font&gt; &lt;font color="#ff8000"&gt;Length (physical) 0&lt;/font&gt;  &lt;/p&gt;  &lt;p&gt;For the third row, containing the NULL value, the page dump appears as follows:    &lt;br /&gt;&lt;font color="#008040"&gt;Slot 2, Offset 0x7e, Length 9      &lt;br /&gt;Record Type = PRIMARY_RECORD         &lt;br /&gt;Record Attributes =  NULL_BITMAP     &lt;br /&gt;&lt;font color="#ff8000"&gt;Record Size = 9&lt;/font&gt;       &lt;br /&gt;Memory Dump @0x61EEC07E       &lt;br /&gt;&lt;/font&gt;&lt;font color="#008040"&gt;00000000:   10000400 01000108 00?????????????????&lt;/font&gt;&lt;font color="#ff0000"&gt;.........&lt;/font&gt;                &lt;br /&gt;&lt;font color="#008040"&gt;Slot 2 Column 1 Offset 0x0 Length 0&lt;/font&gt; &lt;font color="#ff8000"&gt;Length (physical) 0&lt;/font&gt;  &lt;/p&gt;  &lt;p&gt;The items highlighted in &lt;font color="#ff0000"&gt;red&lt;/font&gt; represent the plain text values as well as the bytes allocated for its storage. The "record size" value in &lt;font color="#ff8000"&gt;orange&lt;/font&gt; identifies the allocated storage space for the entire row (all columns plus metadata) in which the value is stored. In our case our row consists of only a single column. The "length (physical)" value, also in &lt;font color="#ff8000"&gt;orange&lt;/font&gt;, identifies the physical length, in bytes, of the plain text as it is being stored.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Evaluation&lt;/strong&gt;     &lt;br /&gt;With the MyCharTest table we see that in all three rows the record size remains the same; while the MyVarCharTest table varies. This dynamic shows that the MyCharTest is allocating the full amount of physical storage for the value regardless of the physical length of the value being stored.&lt;/p&gt;  &lt;p&gt;Another interesting observation was how the "" value was handled in these tests. In our setup for this test we evaluated the length of our values without the influence of the table column data type. The "" value returned 0 bytes in length in this evaluation. The page dump for the MyCharTest table shows that the physical length for the "" value is 10 bytes; while the MyVarCharTest table page dump shows the physical length for the "" value as 0 bytes. The physical length of the "1234567890" and NULL values did not vary in physical length. interesting.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Answer&lt;/strong&gt;     &lt;br /&gt;After all of the above, both aspects of my friend's question was finally answered.     &lt;br /&gt;"W&lt;em&gt;hen a NULL value is stored in a varchar data type, how much memory is allocated in its storage.&lt;/em&gt;":     &lt;br /&gt;No memory is allocated for the storage of a NULL value. (Beyond the row's metadata)    &lt;br /&gt; "...&lt;em&gt;and how can I verify it&lt;/em&gt;.":     &lt;br /&gt;Check out my blog.&lt;/p&gt;  &lt;p&gt;... and now it's time for a second slice of pizza. ;D&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=73992" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry><entry><title>Encryption and Backup Files</title><link rel="alternate" type="text/html" href="http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/01/73928.aspx" /><id>http://www.simple-talk.com/community/blogs/johnm/archive/2009/07/01/73928.aspx</id><published>2009-07-01T09:24:00Z</published><updated>2009-07-01T09:24:00Z</updated><content type="html">&lt;p&gt;In the efforts to protect sensitive data there are some considerations that expand beyond its storage within database; more specifically, the backup files that are generated through the database backup process. Backup files are often kept on devices or media that are removed from the database server and stored in a separate location. If not properly secured these devices can be stealthily snatched away, exposing the backup files contained within.&lt;/p&gt;  &lt;p&gt;If you were to open a backup file in a program like Notepad, your first impression is that the file contains a bunch of garbley-gunk resulting in the false perception that any plain text sensitive data in the backup file cannot be disclosed by simply scanning the raw backup file. In reality, the data in the database that is stored in plain text is not modified and appears in the backup files as plain text. &lt;/p&gt;  &lt;p&gt;To see this for yourself, obtain a plain text value that has not been encrypted or hashed in your database, such as a credit card number or Social Security Number. Open your most recent backup file in an editor like Notepad, Wordpad or &lt;a href="http://www.textpad.com/"&gt;Textpad&lt;/a&gt; and perform a search for that value. You will discover that the sensitive data that is in plain text within the database also is in plain text in the backup file.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/sqlserver/2008/en/us/enterprise.aspx"&gt;Microsoft SQL Server 2008&lt;/a&gt;, Enterprise Edition, introduced Transparent Data Encryption (TDE)&amp;nbsp; as a new feature that was designed to address this issue. This feature encrypts the physical files of the database. This includes any backup files that are generated through the native backup functionality. &lt;/p&gt;  &lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/bb677241.aspx"&gt;Database Encryption Key&lt;/a&gt; (DEK) is a key that was introduced to the &lt;a href="http://msdn.microsoft.com/en-us/library/ms189586.aspx"&gt;encryption key hierarchy&lt;/a&gt; in support of the TDE feature. The DEK encrypts the physical files using one of the following algorithms:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Advanced Encryption Standard (AES) using key length options of 128, 192 or 256 bit. &lt;/li&gt;    &lt;li&gt;Triple DES 3 Key which is an expanded key length version of Triple DES using a 192 bit key. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For a more in depth exploration of TDE and backup/recovery, check out my blog entry with the title "&lt;a href="/community/blogs/johnm/archive/2008/11/14/70492.aspx"&gt;TDE: Under The Hood With Backup&lt;/a&gt;".&lt;/p&gt;  &lt;p&gt;For those who do not have Microsoft SQL Server 2008, Enterprise Edition, or do not wish to implement TDE, the need to protect your database backup files remains. There are many third-party backup products available on the market that provide encryption to the backup files that they generate. Three popular options are:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.quest.com/litespeed-for-sql-server/features-benefits.aspx"&gt;&lt;strong&gt;LiteSpeed for SQL Server&lt;/strong&gt;&lt;/a&gt; (Quest Software: Price not published)     &lt;br&gt;This product encrypts backup files using:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Advanced Encryption Standard (AES) which uses a 256 bit key. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The encryption feature of this product has been available for many versions. The current version of this product is 5.1 which added features such as the ability to define when to perform a differential or full backup, support for SQL Server 2000/2005 Standard Edition, native log shipping conversion and more. For more details on the latest release check out Quest Software's &lt;a href="http://www.quest.com/litespeed-for-sql-server/release-information.aspx"&gt;release information&lt;/a&gt; page.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.idera.com/Products/SQL-Server/SQL-safe-backup-Technical-Features/"&gt;&lt;strong&gt;SQL Safe Backup&lt;/strong&gt;&lt;/a&gt; (Idera: $1,195 - estimated)     &lt;br&gt;This product offers the user a choice of the algorithm used to protect the backup files. The available options are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Data Encryption Standard (DES) which uses a 64 bit key. &lt;em&gt;(not recommended)&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Triple DES which uses a 168 bit key. &lt;/li&gt;    &lt;li&gt;RC2 which uses a 128 bit key. &lt;/li&gt;    &lt;li&gt;Advanced Encryption Standard (AES) which uses a 256 bit key. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The AES 256 bit key encryption option is new with its current version, 5.0, which became available on &lt;a href="http://www.idera.com/Action/Show.aspx?ThisQuery=NewsDetail&amp;amp;ThisID=181"&gt;June 29, 2009&lt;/a&gt;. This version also provides log shipping as new functionality. For more details on the latest version of this product, check out Idera's "&lt;a href="http://www.idera.com/Products/SQL-Server/SQL-safe-backup-What%27s%20New/"&gt;What's New&lt;/a&gt;" page.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.red-gate.com/products/sql_backup/SQL_Backup_USD.pdf"&gt;&lt;strong&gt;SQL Backup Pro&lt;/strong&gt;&lt;/a&gt; (Red-Gate Software: $795 - estimated)     &lt;br&gt;This product encrypts backup files using:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Advanced Encryption Standard (AES) algorithm with an option of 128 or 256 bit key length. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The encryption features of this product have existed since its initial release. Version 4 introduced the 256 bit key option. At the time of this blog entry the current version is 5.4. &lt;a href="http://tinyurl.com/99lsfu"&gt;Version 6.0&lt;/a&gt; is slated for release this Summer. This new release will include features such as handling of network outages during backup, "self-healing" log shipping, advanced compression algorithm and much more. For more details check out Red-Gate's &lt;a href="http://www.red-gate.com/products/sql_backup/features.htm"&gt;fact sheet&lt;/a&gt; for the release of version 6.0.&lt;/p&gt;&lt;img src="http://www.simple-talk.com/community/aggbug.aspx?PostID=73928" width="1" height="1"&gt;</content><author><name>Johnm</name><uri>http://www.simple-talk.com/community/user/Profile.aspx?UserID=13712</uri></author></entry></feed>