tag:blogger.com,1999:blog-167712592024-03-13T20:11:06.921-07:00SQL Server Code,Tips and Tricks, Performance TuningA blog about SQL Server, Books, Movies and life in generalUnknownnoreply@blogger.comBlogger801125tag:blogger.com,1999:blog-16771259.post-4666206916228098012021-08-02T07:14:00.003-07:002021-08-02T07:16:05.311-07:00How to connect to a SQL Server instance on a different domain and a non default port number?<p> </p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a></p><p>We have several domains at my job, we have a dev domain, a prod domain and then several other domains. Recently we had some domain changes where we would connect to a different domain when logging in from the laptops.</p><p>When opening up SSMS and connecting to the SQL Server instances, we now need to use a fully qualified domain name (FQDN) and also specify the port number and the instance name. This could seem a little confusing if you have never done this</p><p><br /></p><p>Here is what it looks like if for example your instance is listening on port 8000, the instance name is SQL01, the server name is DevSQL01 and the domain name is SQLRules.net</p><p><br /></p><p>You would put the following in server name</p><p>DevSQL01.SQLRules.net,8000\SQL01</p><p><br /><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKwknbnFkQv_TP0vsK9lHjf9nf594-DqteKnAVm8ARrt5jMC2bTlQLs_Y_qrBtBKvU8Ucbz5y7BVKf9Yw2LDR97ZwlvcEKJFE3Lh1kAfRbARdgLeI1v4JbVG-MpNuU7fy6sMO9/s1501/SQLServerConnection.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="SQLServerConnection" border="0" data-original-height="488" data-original-width="1501" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKwknbnFkQv_TP0vsK9lHjf9nf594-DqteKnAVm8ARrt5jMC2bTlQLs_Y_qrBtBKvU8Ucbz5y7BVKf9Yw2LDR97ZwlvcEKJFE3Lh1kAfRbARdgLeI1v4JbVG-MpNuU7fy6sMO9/w640-h208/SQLServerConnection.PNG" title="SQLServerConnection" width="640" /></a></div><br /><p><br /></p><p>To make is easier to see... here it is again with different colors for the different parts</p><p><b><span style="color: #38761d;">DevSQL01</span>.<span style="color: #ffa400;">SQLRules.net</span>,<span style="color: red;">8000</span>\<span style="color: #2b00fe;">SQL01</span></b></p><p>The server name is <b><span style="color: #38761d;">DevSQL01</span></b></p><p>The domain name is<span style="color: #ffa400;"> </span><b><span style="color: #ffa400;">SQLRules.net</span></b></p><p>The port number is <span style="color: red;"><b>8000</b></span></p><p>The instance name in <span style="color: #2b00fe;"><b>SQL01</b></span></p><p><br /></p><p>The fully qualified domain name (FQDN) in this case is of course DevSQL01.SQLRules.net</p><p>Hopefully this helps someone in the future</p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-16771259.post-63350225922732351492021-03-15T06:25:00.004-07:002021-03-15T06:26:21.388-07:00After 20+ years in IT .. I finally discovered this useful command<p>Very similar to my <a href="https://sqlservercode.blogspot.com/2019/02/after-20-years-in-it-i-finally-discovered-this.html">After 20+ years in IT .. I finally discovered this...</a> post, I discovered yet another command I should have know about</p><p>Originally I was not going to write this post, but after I found out that several other people didn't know this, I figured what the heck, why not, maybe someone will think this is cool as well</p><p><br /></p><p>Open up a command prompt or powershell command window, , navigate to a folder, type in <b>tree</b>... hit enter</p><p>Here is what I see</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSV66wjoysE2VA9vS7aG_EY011akuXAfOrsQQx77n1rkxTtdxVs9u78K0Y-Zzrk8BVkpQnoEf4UhqslCtWNA5_449BcXib2ygK4TqAeQZ_AgrWjSU7-kKMm58VigE5iZ1AWJh8/s1525/CMD_TRee.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Tree dos command" border="0" data-original-height="1525" data-original-width="1452" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSV66wjoysE2VA9vS7aG_EY011akuXAfOrsQQx77n1rkxTtdxVs9u78K0Y-Zzrk8BVkpQnoEf4UhqslCtWNA5_449BcXib2ygK4TqAeQZ_AgrWjSU7-kKMm58VigE5iZ1AWJh8/w381-h400/CMD_TRee.PNG" width="381" /></a></div><br /><p>I was watching a Pluralsight course and the person typed in the tree command.. and I was like whoaaaa.. How do I not know this? Perhaps maybe because I don't use the command window all that much? Anyway I thought that this was pretty cool</p><p>As you can see tree list all the directories and sub directories in a tree like structure. This is great to quickly see all the directories in one shot</p><p>The same command will work in Powershell</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge7sNr55KhFqrmtAlljXj4gBnoWk3YmbSbX9f1V1zt_BeCxuVEQ1rulP0zqogrtiARbwhJkAEwh_rdh2iURr-9meDDhDZ-gA1Fr6E6G9bIJsaeYw_1yUheqCcun3nQpbgZSYDF/s1655/CMD_TRee_Powershell.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="tree command in Powershell" border="0" data-original-height="1382" data-original-width="1655" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge7sNr55KhFqrmtAlljXj4gBnoWk3YmbSbX9f1V1zt_BeCxuVEQ1rulP0zqogrtiARbwhJkAEwh_rdh2iURr-9meDDhDZ-gA1Fr6E6G9bIJsaeYw_1yUheqCcun3nQpbgZSYDF/w400-h334/CMD_TRee_Powershell.PNG" width="400" /></a></div><br /><p>Finally, here is an image of the command window output as well as the explorer navigation pane side by side</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrg48LV5CUX4OpMSHv990zjiCXLBLUVmNZIImq7-pAR0n9tO-H7Qrl1W8zn3ZDAiDS7dTpZjIw3gwxiITINv0ZlWHKMAYAo0uwKmqSJKI3Mgd6ZtDpRIQS4YUcyJd_8FmsybDH/s2048/CMM_TREE_Explorer.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="command window output as well as the explorer navigation pane side by side" border="0" data-original-height="1158" data-original-width="2048" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrg48LV5CUX4OpMSHv990zjiCXLBLUVmNZIImq7-pAR0n9tO-H7Qrl1W8zn3ZDAiDS7dTpZjIw3gwxiITINv0ZlWHKMAYAo0uwKmqSJKI3Mgd6ZtDpRIQS4YUcyJd_8FmsybDH/w640-h362/CMM_TREE_Explorer.PNG" title="command window output as well as the explorer navigation pane side by side" width="640" /></a></div><br /><p>Hopefully this will be useful to someone</p><p><br /></p><p><br /></p><p><br /></p>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-16771259.post-12701107017852609032020-05-22T06:40:00.001-07:002020-10-17T14:08:04.532-07:00PostgreSQL adds FETCH FIRST WITH TIES.. just like TOP n WITH TIES in SQL ServerPostgreSQL 13 Beta 1 was released yesterday, you can read the release notes here<br />
<br />
<a href="https://www.postgresql.org/about/news/2040/">https://www.postgresql.org/about/news/2040/</a><br />
<br />
One thing that caught my eye was this statement in the release notes<br />
<br />
<i>PostgreSQL 13 brings more convenience to writing queries with features like FETCH FIRST WITH TIES, which returns any additional rows that match the last row.</i><br />
<br />
This is I guess exactly like TOP WITH TIES in SQL Server. I believe this has been around in SQL Server since at least version 7. How many times have I used it in code that was deployed in the last 20 years? I believe I have used WITH TIES only once. It does make for great interview questions and SQL puzzles :-)<br />
<br />
<br />
So let's take a quick look at how TOP WITH TIES works in SQL Server. The first thing we will do is look at what Books On Line says about <a href="https://docs.microsoft.com/en-us/sql/t-sql/queries/top-transact-sql?view=sql-server-ver15">TOP</a><br />
<i><br /></i>
<br />
<blockquote class="tr_bq">
<i>WITH TIES </i><i>Returns two or more rows that tie for last place in the limited results set. You must use this argument with the ORDER BY clause. WITH TIES might cause more rows to be returned than the value specified in expression. For example, if expression is set to 5 but two additional rows match the values of the ORDER BY columns in row 5, the result set will contain seven rows.</i><i>You can specify the TOP clause with the WITH TIES argument only in SELECT statements, and only if you've also specified the ORDER BY clause. The returned order of tying records is arbitrary. ORDER BY doesn't affect this rule.</i></blockquote>
<br />
Time to get started and write some code to see this in action<br />
<br />
First create this table of students and insert some data<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #TopExample(GradeAverage <span style="color: #007020;">int</span>, Student <span style="color: #007020;">varchar</span>(<span style="color: #6600ee; font-weight: bold;">100</span>))
<span style="color: #008800; font-weight: bold;">INSERT</span> #TopExample <span style="color: #008800; font-weight: bold;">VALUES</span>(<span style="color: #6600ee; font-weight: bold;">99.00</span>,<span style="background-color: #fff0f0;">'Plato'</span>),
(<span style="color: #6600ee; font-weight: bold;">98</span>,<span style="background-color: #fff0f0;">'Socrates'</span>),
(<span style="color: #6600ee; font-weight: bold;">95</span>,<span style="background-color: #fff0f0;">'Diogenes the Cynic'</span>),
(<span style="color: #6600ee; font-weight: bold;">94</span>,<span style="background-color: #fff0f0;">'Antisthenes'</span>),
(<span style="color: #6600ee; font-weight: bold;">94</span>,<span style="background-color: #fff0f0;">'Demetrius'</span>),
(<span style="color: #6600ee; font-weight: bold;">50</span>,<span style="background-color: #fff0f0;">'Denis'</span>)</pre>
<br />
As you can see, I am not a very good student :-(<br />
<br />
If you do a regular TOP 4 query like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #6600ee; font-weight: bold;">4</span> GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span></pre>
<br />
You will get back these results<br />
<br />
<pre>GradeAverage Student
99 Plato
98 Socrates
95 Diogenes the Cynic
94 Demetrius</pre>
<br />
<br />
As you can see we are missing another student with a grade of 94, this is Antisthenes<br />
<br />
This is easily fixed by adding WITH TIES to the query<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #6600ee; font-weight: bold;">4</span> <span style="color: #008800; font-weight: bold;">WITH</span> TIES GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span></pre>
<br />
Now, you will get back these results, as you can see, you now have 5 rows and both rows with a grade average of 94 are included<br />
<br />
<pre>GradeAverage Student
99 Plato
98 Socrates
95 Diogenes the Cynic
94 Demetrius
94 Antisthenes</pre>
<br />
<br />
Another way to do the same as WITH TIES is by using DENSE_RANK. That query looks like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">;<span style="color: #008800; font-weight: bold;">WITH</span> c <span style="color: #008800; font-weight: bold;">AS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> DENSE_RANK() <span style="color: #008800; font-weight: bold;">OVER</span> (<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span>) <span style="color: #008800; font-weight: bold;">AS</span> dens,
GradeAverage,Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample)
<span style="color: #008800; font-weight: bold;">SELECT</span> GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> c <span style="color: #008800; font-weight: bold;">WHERE</span> dens <=<span style="color: #6600ee; font-weight: bold;">4</span>
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span> </pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<div>
You will get back these same results again, you now have 5 rows and both rows with a grade average of 94 are included as well
</div>
<pre style="color: black;">GradeAverage Student
99 Plato
98 Socrates
95 Diogenes the Cynic
94 Demetrius
94 Antisthenes
</pre>
<br />
Using DENSE_RANK is bit more code, but if portability is a concern, it might be a better choice <br />
<br />
There you go a post about a feature you will never use :-) <br />
<br />
If you want to run all the queries in one shot here is all the code<br />
<div>
<br />
<span style="color: #333333;"><br /></span>
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #TopExample(GradeAverage <span style="color: #007020;">int</span>, Student <span style="color: #007020;">varchar</span>(<span style="color: #6600ee; font-weight: bold;">100</span>))
<span style="color: #008800; font-weight: bold;">INSERT</span> #TopExample <span style="color: #008800; font-weight: bold;">VALUES</span>(<span style="color: #6600ee; font-weight: bold;">99.00</span>,<span style="background-color: #fff0f0;">'Plato'</span>),
(<span style="color: #6600ee; font-weight: bold;">98.00</span>,<span style="background-color: #fff0f0;">'Socrates'</span>),
(<span style="color: #6600ee; font-weight: bold;">95.00</span>,<span style="background-color: #fff0f0;">'Diogenes the Cynic'</span>),
(<span style="color: #6600ee; font-weight: bold;">94.00</span>,<span style="background-color: #fff0f0;">'Antisthenes'</span>),
(<span style="color: #6600ee; font-weight: bold;">94.00</span>,<span style="background-color: #fff0f0;">'Demetrius'</span>),
(<span style="color: #6600ee; font-weight: bold;">50.00</span>,<span style="background-color: #fff0f0;">'Denis'</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #6600ee; font-weight: bold;">4</span> GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #6600ee; font-weight: bold;">4</span> <span style="color: #008800; font-weight: bold;">WITH</span> TIES GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span>
;<span style="color: #008800; font-weight: bold;">WITH</span> c <span style="color: #008800; font-weight: bold;">AS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> DENSE_RANK() <span style="color: #008800; font-weight: bold;">OVER</span> (<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span>) <span style="color: #008800; font-weight: bold;">AS</span> dens,
GradeAverage,Student
<span style="color: #008800; font-weight: bold;">FROM</span> #TopExample)
<span style="color: #008800; font-weight: bold;">SELECT</span> GradeAverage, Student
<span style="color: #008800; font-weight: bold;">FROM</span> c <span style="color: #008800; font-weight: bold;">WHERE</span> dens <=<span style="color: #6600ee; font-weight: bold;">4</span>
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> GradeAverage <span style="color: #008800; font-weight: bold;">DESC</span>
<span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #TopExample</pre>
<span style="color: #333333;"><br /></span>
<br />
<pre style="line-height: 16.25px;"><span style="color: #333333;">And here is what it all looks like in SSMS, code and output
</span><div class="separator" style="clear: both; color: #333333; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfAy18cduODhfHRrXIrVMJiwBsvn3jgF2F4fqq8MRYLek50EjcSjQrkg4LV-8_9ztChMS-cnaoUdb5z87qrfZE7iJZsnLiy6MYocUBWXBfY9Y-toqjBo4z4dikTINUGS3QLJYZ/s1600/SSMSOutput.JPG" style="margin-left: 1em; margin-right: 1em;"><img alt="PostgreSQL adds FETCH FIRST WITH TIES.. just like TOP n WITH TIES in SQL Server Query in SSMS" border="0" data-original-height="990" data-original-width="768" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfAy18cduODhfHRrXIrVMJiwBsvn3jgF2F4fqq8MRYLek50EjcSjQrkg4LV-8_9ztChMS-cnaoUdb5z87qrfZE7iJZsnLiy6MYocUBWXBfY9Y-toqjBo4z4dikTINUGS3QLJYZ/s640/SSMSOutput.JPG" title="PostgreSQL adds FETCH FIRST WITH TIES.. just like TOP n WITH TIES in SQL Server Query in SSMS" width="496" /></a></div>
<span style="color: #333333;">
</span></pre>
</div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-16771259.post-57969881088709096022020-05-06T11:43:00.000-07:002020-05-06T11:47:53.620-07:00You know about waitfor delay but did you know there is a waitfor time?<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
I was looking at some code I wrote the other day and noticed the WAITFOR command.. This got me thinking. How many times have I used WAITFOR in code, probably as much as I have used NTILE :-)<br />
<br />
I looked at the <a href="https://docs.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql?view=sql-server-ver15">documentation for WAITFOR</a> and notice there is TIME in addition to DELAY. Oh that is handy, I always rolled my own ghetto-style version by calculating how long it would be until a specific time and then I would use that in the WAITFOR DELAY command<br />
<br />
Why would you use the WAITFOR command?<br />
<br />
The WAITFOR command can be used to delay the execution of command for a specific duration or until a specific time occurs. <a href="https://docs.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql?view=sql-server-ver15">From Books On Line</a>, the description is as follows:<br />
<br />
<br />
<br />
<i>Blocks the execution of a batch, stored procedure, or transaction until either a specified time or time interval elapses, or a specified statement modifies or returns at least one row.</i><br />
<i><br /></i>
<i>WAITFOR </i><br />
<i>{ </i><br />
<i> DELAY 'time_to_pass' </i><br />
<i> | TIME 'time_to_execute' </i><br />
<i> | [ ( receive_statement ) | ( get_conversation_group_statement ) ] </i><br />
<i> [ , TIMEOUT timeout ] </i><br />
<i>} </i><br />
<i><br /></i>
<i><br /></i>
<i><br /></i>
<i>Arguments</i><br />
<i>DELAY</i><br />
<i>Is the specified period of time that must pass, up to a maximum of 24 hours, before execution of a batch, stored procedure, or transaction proceeds.</i><br />
<i><br /></i>
<i>'time_to_pass'</i><br />
<i>Is the period of time to wait. time_to_pass can be specified either in a datetime data format, or as a local variable. Dates can't be specified, so the date part of the datetime value isn't allowed. time_to_pass is formatted as hh:mm[[:ss].mss].</i><br />
<i><br /></i>
<i>TIME</i><br />
<i>Is the specified time when the batch, stored procedure, or transaction runs.</i><br />
<i><br /></i>
<i>'time_to_execute'</i><br />
<i>Is the time at which the WAITFOR statement finishes. time_to_execute can be specified in a datetime data format, or it can be specified as a local variable. Dates can't be specified, so the date part of the datetime value isn't allowed. time_to_execute is formatted as hh:mm[[:ss].mss] and can optionally include the date of 1900-01-01.</i><br />
<br />
<br />
WAITFOR with a receive_statement or get_conversation_group_statement is applicable only to Service Broker messages. I will not cover those in this post<br />
<br />
<br />
<br />
I must admit that I only use these commands a couple of times a year when running something ad-hoc. In code, I will use WAITFOR DELAY when doing a back fill of data, and the table is replicated. In that case I will batch the data and after each batch is completed I will pause for a second or so. The reason I am doing this is because I don't want to increase replication latency, after all, I am a nice guy<br />
<br />
<br />
<b>WAITFOR TIME </b><br />
<br />
Let's take a look how you would use the WAITFOR command. I will start with WAITFOR TIME<br />
<br />
<br />
The command is very easy.. if you want the print command to run at 09:57:16, you would do the following<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">WAITFOR <span style="color: #007020;">TIME</span> <span style="background-color: #fff0f0;">'09:57:16'</span>
PRINT <span style="background-color: #fff0f0;">'DONE '</span> </pre>
<pre style="background-color: white; color: #333333; line-height: 16.25px;">
</pre>
The seconds are optional, if you want it to run at 9 hours and 57 minutes, you can do the following<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">WAITFOR <span style="color: #007020;">TIME</span> <span style="background-color: #fff0f0;">'09:57'</span>
PRINT <span style="background-color: #fff0f0;">'DONE '</span> </pre>
<br />
One thing to know is that you can't grab the output from a time data type and use that in your WAITFOR TIME command. The following will blow up<br />
<br />
<pre style="background-color: white; color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(time, getdate()) <span style="color: #888888;">--'09:57:16.9600000'</span>
WAITFOR TIME <span style="background-color: #fff0f0;">'09:57:16.9600000'</span></pre>
<br />
<i>Msg 148, Level 15 , State 1, Line 32</i><br />
<i>Incorrect time syntax in time string '09:57:16.9600000' used with WAITFOR.</i><br />
<br />
What you need to do is strip everything after the dot.<br />
<br />
We need the command to be the following<br />
<br />
<br />
<pre style="background-color: white; color: #333333; line-height: 16.25px;">WAITFOR TIME <span style="background-color: #fff0f0;">'09:57:16'</span></pre>
<br />
There are two ways to accomplish this... first way is by using PARSENAME, I blogged about that function several times, the first time here: <a href="http://sqlservercode.blogspot.com/2007/02/ten-sql-server-functions-that-you.html">Ten SQL Server Functions That You Hardly Use But Should</a><br />
<br />
All you have to tell SQL Server which part you want, if you use PARSENAME,1 you will get everything after the dot, if you use PARSENAME,2 you will get everything before the dot.<br />
<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;">1
2</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> PARSENAME(<span style="background-color: #fff0f0;">'09:57:16.9600000'</span>,<span style="color: #0000dd; font-weight: bold;">2</span>),
PARSENAME(<span style="background-color: #fff0f0;">'09:57:16.9600000'</span>,<span style="color: #0000dd; font-weight: bold;">1</span>)</pre>
</td></tr>
</tbody></table>
<br />
This returns the following<br />
<br />
09:57:16<span style="white-space: pre;"> </span> 9600000<br />
<br />
<br />
The easiest way would have been to just use time(0) instead<br />
<br />
<pre style="background-color: white; color: #333333; line-height: 16.25px;"><table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;">1
2</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(time, getdate()) ,<span style="color: #888888;">--'09:57:16.9600000'</span>
<span style="color: #008800; font-weight: bold;">CONVERT</span>(time(<span style="color: #0000dd; font-weight: bold;">0</span>), getdate()) <span style="color: #888888;">--'09:57:16</span></pre>
</td></tr>
</tbody></table>
</pre>
<br />
Below is a complete example that will wait for 10 seconds to run the PRINT statement on line 12 if you run the whole code block in 1 shot.<br />
<br />
Also notice that I use a variable with the WAITFOR TIME command on line 9. The caveat with that is that the variable can't be a time datatype. This is why I use a varchar datatype and store the value of the time data type in it. The reason I use the time datatype in my procs is so that I don't have to do a lot of validations when someone is calling the proc. If they pass in a string that can't be converted.. the proc won't even run... it will fail right at the proc call itself<br />
<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;"> 1
2
3
4
5
6
7
8
9
10
11
12</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DECLARE</span> @DelayTime time(<span style="color: #0000dd; font-weight: bold;">0</span>)= GETDATE()
PRINT @DelayTime
<span style="color: #008800; font-weight: bold;">SELECT</span> @DelayTime =DATEADD(<span style="color: #008800; font-weight: bold;">second</span>,<span style="color: #0000dd; font-weight: bold;">10</span>,@DelayTime)
PRINT @DelayTime
<span style="color: #008800; font-weight: bold;">DECLARE</span> @d <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">100</span>) = @DelayTime <span style="color: #888888;">-- you have to use varchar in command</span>
WAITFOR TIME @d
<span style="color: #888888;">-- Run your command here</span>
PRINT <span style="background-color: #fff0f0;">'DONE '</span> + <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),<span style="color: #008800; font-weight: bold;">CONVERT</span>(time(<span style="color: #0000dd; font-weight: bold;">0</span>), getdate()))</pre>
</td></tr>
</tbody></table>
<br />
<br />
What is printed is the following<br />
<br />
<br />
10:49:48<br />
10:49:58<br />
DONE 10:49:58<br />
<br />
Now when would you really use WAITFOR TIME? You can accomplish the same with a scheduled job, the only time I use WAITFOR TIME is if I want a quick count of want to run something at a specific time but I know I won't be at my desk and I can't create a job without a ticket<br />
<br />
But you also have to be aware that if your connection gets lost to the SQL Server instance, your command won't execute<br />
<br />
<br />
<b>WAITFOR DELAY</b><br />
<br />
The WAITFOR DELAY command is similar to the WAITFOR TIME command, instead of waiting for a time, the command pauses for a specific period<br />
<br />
Like I said before, I use WAITFOR DELAY as well as a batch size in my back fill procs. Both can be passed in, if you do a load during a weekday, your delay would be longer than on a weekend.<br />
<br />
<br />
Sometimes I need to see how many rows are getting inserted every minute.. or something similar<br />
I will then combine WAITFOR DELAY and the batch terminator with a count number to execute the batch of statements more than once<br />
<br />
Here is such an example, it will run the INSERT statement 20 times, it will pause 1 minute between each execution<br />
<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;">1
2
3
4</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">INSERT</span> #temp(SomeCol, SomeTimeStamp)
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*), GETDATE() <span style="color: #008800; font-weight: bold;">FROM</span> sometable
WAITFOR DELAY <span style="background-color: #fff0f0;">'00:01:00'</span>
<span style="color: #008800; font-weight: bold;">GO</span> <span style="color: #0000dd; font-weight: bold;">20</span></pre>
</td></tr>
</tbody></table>
<br />
<br />
That's all for this post.<br />
<br />
Do you use the WAITFOR command, if so, what do you use it for?<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-3695128422923521262020-01-20T09:43:00.001-08:002020-01-20T09:45:41.736-08:00TVPs vs Memory Optimized TVPs<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
The other day I was thinking about the blog post <a href="https://docs.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/faster-temp-table-and-table-variable-by-using-memory-optimization?view=sql-server-ver15">Faster temp table and table variable by using memory optimization</a> I read a while back. Since you can't believe anything on the internets (no disrespect to whoever wrote that post) , I decided to take this for a test<br />
<br />
In this post I will be creating 2 databases, one is a plain vanilla database and the other, a database that also has a file group that contains memory optimized data<br />
<br />
I will also be creating a table type in each database, a plain one and a memory optimized one in the memory optimized database<br />
<br />
So lets get started, first I will create the regular database and the regular table type<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">DATABASE</span> TempTVP
<span style="color: #008800; font-weight: bold;">GO</span>
USE TempTVP
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TYPE</span> dbo.DataProcessingType <span style="color: #008800; font-weight: bold;">AS</span> <span style="color: #008800; font-weight: bold;">TABLE</span>(
SomeDate datetime <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeSymbol <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">40</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeValue <span style="color: #007020;">numeric</span>(<span style="color: #0000dd; font-weight: bold;">24</span>, <span style="color: #0000dd; font-weight: bold;">10</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeDescription <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
<span style="color: #008800; font-weight: bold;">index</span> tvp_temp (SomeDate, SomeSymbol))
<span style="color: #008800; font-weight: bold;">GO</span></pre>
</td></tr>
</tbody></table>
<br />
<br />
Now I will create the memory optimized database and the memory optimized table type<br />
In order for the database to be able to use memory optimized code, you need to add a filegroup and tell SQL Server it contains memory optimized data, after that is created, you add a file to that file group.<br />
<br />
The table type syntax is identical except for the line (WITH (MEMORY_OPTIMIZED = ON);) at the end<br />
<br />
Here is what the script looks like<br />
<br />
<br />
<pre style="background-color: white; color: #333333; line-height: 16.25px;"></pre>
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">DATABASE</span> TempTVPHekaton
<span style="color: #008800; font-weight: bold;">GO</span>
USE TempTVPHekaton
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">ALTER</span> <span style="color: #008800; font-weight: bold;">DATABASE</span> [TempTVPHekaton] <span style="color: #008800; font-weight: bold;">ADD</span> FILEGROUP [Hekaton_Data]
<span style="color: #008800; font-weight: bold;">CONTAINS</span> MEMORY_OPTIMIZED_DATA
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">ALTER</span> <span style="color: #008800; font-weight: bold;">DATABASE</span> [TempTVPHekaton] <span style="color: #008800; font-weight: bold;">ADD</span> FILE (NAME=<span style="background-color: #fff0f0;">'Hekaton_Data_file'</span>,
FILENAME=<span style="background-color: #fff0f0;">'C:\Data\ekaton_Data_file.mdf'</span>) <span style="color: #008800; font-weight: bold;">TO</span> FILEGROUP Hekaton_Data;
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TYPE</span> dbo.DataProcessingType <span style="color: #008800; font-weight: bold;">AS</span> <span style="color: #008800; font-weight: bold;">TABLE</span>(
SomeDate datetime <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeSymbol <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">40</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeValue <span style="color: #007020;">numeric</span>(<span style="color: #0000dd; font-weight: bold;">24</span>, <span style="color: #0000dd; font-weight: bold;">10</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
SomeDescription <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
<span style="color: #008800; font-weight: bold;">index</span> tvp_temp (SomeDate, SomeSymbol))
<span style="color: #008800; font-weight: bold;">WITH</span> (MEMORY_OPTIMIZED = <span style="color: #008800; font-weight: bold;">ON</span>);
<span style="color: #008800; font-weight: bold;">GO</span></pre>
</td></tr>
</tbody></table>
<br />
Now that we have our two database, lets create a very simple stored proc in each database, all it does is store the row count from the table valued parameter passed in into a variable<br />
<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;"> 1
2
3
4
5
6
7
8
9
10</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">PROCEDURE</span> prTestTVP @tvp DataProcessingType readonly
<span style="color: #008800; font-weight: bold;">AS</span>
<span style="color: #008800; font-weight: bold;">SET</span> NOCOUNT <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @<span style="color: #008800; font-weight: bold;">Count</span> <span style="color: #007020;">int</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @<span style="color: #008800; font-weight: bold;">Count</span> = <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">FROM</span> @tvp
<span style="color: #008800; font-weight: bold;">GO</span></pre>
</td></tr>
</tbody></table>
<br />
Now it is time to generate the test script<br />
<br />
The text script will call the stored procedure 1000 times passing in a table valued parameter<br />
The test script will populate the table type with 1000 rows, the data looks like this<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXN2cVzA3q7_8GTfatEoDEnAZ0rDdT5mJRC9-r6b-7DgYlW-fmQF82eIy30JcLvx6wHIT-reIMUf9EW8TvNxhn7v7c0-SJk3Q6aJr2XqKeakMBywsAppOlhuqzHzQIg3NfOK6/s1600/SSMSOutput.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="407" data-original-width="1215" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXN2cVzA3q7_8GTfatEoDEnAZ0rDdT5mJRC9-r6b-7DgYlW-fmQF82eIy30JcLvx6wHIT-reIMUf9EW8TvNxhn7v7c0-SJk3Q6aJr2XqKeakMBywsAppOlhuqzHzQIg3NfOK6/s640/SSMSOutput.JPG" width="640" /></a></div>
<br />
That data is pushed into the table valued parameter, the proc is called, the table type is cleared out and every 100 iterations the current iteration will be printed<br />
<br />
<table style="color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif;"><tbody>
<tr><td><pre style="line-height: 16.25px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26</pre>
</td><td><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SET</span> NOCOUNT <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @LoopID <span style="color: #007020;">int</span> = <span style="color: #0000dd; font-weight: bold;">1</span>
WHILE @LoopID <= <span style="color: #0000dd; font-weight: bold;">1000</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @tvp DataProcessingType
<span style="color: #008800; font-weight: bold;">INSERT</span> @tvp <span style="color: #888888;">-- add some values</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> DATEADD(d,<span style="color: #007020;">number</span>,<span style="background-color: #fff0f0;">'20200101'</span>) <span style="color: #008800; font-weight: bold;">as</span> SomeDate,
<span style="background-color: #fff0f0;">'X'</span> + STR(<span style="color: #007020;">number</span>) + STR(@LoopID) <span style="color: #008800; font-weight: bold;">as</span> SomeSymbol,
<span style="color: #007020;">number</span> * @LoopID * <span style="color: #0000dd; font-weight: bold;">1</span>.<span style="color: #0000dd; font-weight: bold;">11</span> <span style="color: #008800; font-weight: bold;">as</span> SomeValue,
<span style="color: #008800; font-weight: bold;">LEFT</span>(REPLICATE(<span style="color: #007020;">number</span>,<span style="color: #0000dd; font-weight: bold;">100</span>),<span style="color: #0000dd; font-weight: bold;">100</span>) <span style="color: #008800; font-weight: bold;">as</span> SomeDescription
<span style="color: #008800; font-weight: bold;">FROM</span> master..spt_values
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span> <span style="color: #888888;">-- only numbers</span>
<span style="color: #008800; font-weight: bold;">and</span> <span style="color: #007020;">number</span> < <span style="color: #0000dd; font-weight: bold;">1000</span>
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> NEWID() <span style="color: #888888;">--pseudo-random sort</span>
<span style="color: #008800; font-weight: bold;">EXEC</span> prTestTVP @tvp <span style="color: #888888;">-- CALL proc with 1000 rows</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> @tvp <span style="color: #888888;">-- delete the data since it will be populated again</span>
if @LoopID %<span style="color: #0000dd; font-weight: bold;">100</span> = <span style="color: #0000dd; font-weight: bold;">0</span> <span style="color: #888888;">-- print every 100 iterations</span>
PRINT STR(@LoopID)
<span style="color: #008800; font-weight: bold;">SET</span> @LoopID += <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #888888;">-- add 1 to counter</span>
<span style="color: #008800; font-weight: bold;">END</span></pre>
</td></tr>
</tbody></table>
<br />
<br />
What I did now is take the code, I then pasted the code in 2 different SSMS windows and connected to the TempTVP database, I then executed the code in both windows and let it run. Once it was finished, I noted down how long it took and then changed the connections to the database TempTVPHekaton which is memory optimized and ran the code in both windows as well. I played around with loops of 100, 1000, 2000, I played around as well by populating the table with rows between 1000 and 2048<br />
<br />
Here are some of the results<br />
<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;border-color:#aaa;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#333;background-color:#fff;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#fff;background-color:#f38630;}
.tg .tg-fp3b{font-weight:bold;border-color:#fd6864;text-align:left;vertical-align:middle}
.tg .tg-e5mg{border-color:#fd6864;text-align:left;vertical-align:middle}
</style>
<br />
<table class="tg">
<tbody>
<tr>
<th class="tg-fp3b">DB Storage</th>
<th class="tg-fp3b">Iterations * rows</th>
<th class="tg-fp3b">Percentage of time</th>
</tr>
<tr>
<td class="tg-e5mg">Disk</td>
<td class="tg-e5mg">1000 * 1000</td>
<td class="tg-e5mg">85.37%</td>
</tr>
<tr>
<td class="tg-e5mg">Memory</td>
<td class="tg-e5mg">1000 * 1000</td>
<td class="tg-e5mg">14.63%</td>
</tr>
<tr>
<td class="tg-e5mg"></td>
<td class="tg-e5mg"></td>
<td class="tg-e5mg"></td>
</tr>
<tr>
<td class="tg-e5mg">Disk</td>
<td class="tg-e5mg">1500 * 1000</td>
<td class="tg-e5mg">76.36%</td>
</tr>
<tr>
<td class="tg-e5mg">Memory</td>
<td class="tg-e5mg">1500 * 1000</td>
<td class="tg-e5mg">23.64%</td>
</tr>
<tr>
<td class="tg-e5mg"></td>
<td class="tg-e5mg"></td>
<td class="tg-e5mg"></td>
</tr>
<tr>
<td class="tg-e5mg">Disk</td>
<td class="tg-e5mg">5000 * 100</td>
<td class="tg-e5mg">92.31%</td>
</tr>
<tr>
<td class="tg-e5mg">Memory</td>
<td class="tg-e5mg">5000 * 100</td>
<td class="tg-e5mg">7.69%</td>
</tr>
</tbody></table>
<br />
<br />
So it looks like it is at least 4 times faster, if the table is smaller and you have more iterations, it gets even faster<br />
<br />
<br />
I did run into an issue while testing, if I made it execute 5000 times with a 2000 rows table.. I was greeted by the following error<br />
<br />
<i>Msg 701, Level 17, State 154, Procedure prTestTVP, Line 7 [Batch Start Line 0]</i><br />
<i>There is insufficient system memory in resource pool 'default' to run this query.</i><br />
<br />
This code was running on a laptop where I had 40 tabs open in chrome so there was not a lot of free memory, I also didn't create a resource pool, everything was a default setup<br />
<br />
If you look at the code you will see that I clear out the table after each iteration.<br />
<br />
However the table variable doesn't get out of scope until the loop is finished. In my real time scenario, I don't have this issue, my procs are called by many processes but not in a loop<br />
<br />
To read more about this error start here<br />
<br />
<a href="https://docs.microsoft.com/en-us/archive/blogs/psssql/be-aware-of-701-error-if-you-use-memory-optimized-table-variable-in-a-loop">Be aware of 701 error if you use memory optimized table variable in a loop</a><br />
<br />
<i>This is actually by-design behavior documented in “<a href="https://docs.microsoft.com/en-us/sql/database-engine/memory-optimized-table-variables?view=sql-server-2014&redirectedfrom=MSDN">Memory-Optimized Table Variables</a>”). Here is what is state “Unlike memory-optimized tables, the memory consumed (including deleted rows) by table variables is freed when the table variable goes out of scope)”. With a loop like above, all deleted rows will be kept and consume memory until end of the loop.</i><br />
<br />
<br />
There you go.. if you are using table types, switching them to in memory table types might help your application perform better. But of course as I said before... since you can't believe anything on the internets, test for yourself<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-73613103417260596132019-12-30T11:55:00.000-08:002019-12-30T11:55:22.753-08:00Top 10 posts from the last decade<a data-flickr-embed="true" href="https://www.flickr.com/photos/denisgobo/15946305689/in/shares-bzC2V5/" title="Bokeh for the win"><img alt="Out of focus Christmas tree" height="333" src="https://c2.staticflickr.com/8/7499/15946305689_f28455752a.jpg" title="Bokeh for the win" width="500" /></a><br />
<br />
<span style="font-family: "times new roman", serif;">As we finish the tumultuous 2010s and are ready for the roaring 2020s, I decided to take a quick look at the ten most viewed posts from the past decade. Two of these posts were made posted before 2010</span><br />
<span style="font-family: times new roman, serif;"><br /></span>
<span style="font-family: times new roman, serif;">Without any fanfare, here is the list</span><br />
<span style="font-family: times new roman, serif;"><br /></span>
<span style="font-family: times new roman, serif;"><br /></span>
10. <b><a href="http://sqlservercode.blogspot.com/2016/10/some-cool-sql-server-announcements-sql.html">Some cool SQL Server announcements SQL Graph, Adaptive Query Plan, CTP1 of SQL vNext, SQL Injection detection</a></b><br />
This is my recap of the chalkboard session with the SQL Server team at the SQL Server PASS summit in Seattle.<br />
<div>
<br /></div>
<div>
09. <b><a href="http://sqlservercode.blogspot.com/2006/05/convert-millisecond-to-hhmmss-format.html">Convert Millisecond To "hh:mm:ss" Format</a></b><br />
A very old post showing you how to convert from milliseconds to "hh:mm:ss" format<br />
<br />
08. <b><a href="http://sqlservercode.blogspot.com/2019/06/Can-adding-an-index-make-a-non-SARGable-query-SARGable-instead-of-rewriting-sql-query.html">Can adding an index make a non SARGable query SARGable?</a></b><br />
A post showing you how adding an index can make a query use that index even though the index column doesn't match the query<br />
<br />
07. <b><a href="http://sqlservercode.blogspot.com/2018/09/a-little-less-hate-for-string-or-binary.html">A little less hate for: String or binary data would be truncated in table</a></b><br />
Can you believe they actually managed to accomplish this during the past decade :-)<br />
<br />
06. <b><a href="http://sqlservercode.blogspot.com/2019/03/some-numbers-that-you-will-know-by.html">Some numbers that you will know by heart if you have been working with SQL Server for a while</a></b><br />
After working with SQL Server for a while, you should know most of these<br />
<br />
05. <b><a href="http://sqlservercode.blogspot.com/2017/11/use-t-sql-to-create-caveman-graphs.html">Use T-SQL to create caveman graphs</a></b><br />
One of the shortest post on this site, show you how you can make visually appealing output with a pipe symbol<br />
<br />
04. <a href="http://sqlservercode.blogspot.com/2007/02/ten-sql-server-functions-that-you.html"><b>Ten SQL Server Functions That You Hardly Use But Should</b></a></div>
<div>
A post from 2007 showing some hardly used functions like NULLIF, PARSENAME and STUFF<br />
<br />
03. <a href="http://sqlservercode.blogspot.com/2017/10/your-lack-of-constraints-is-disturbing.html"><b>Your lack of constraints is disturbing</b></a><br />
A post showing the type of constraints available in SQL Server with examples<br />
<br />
02. <b><a href="http://sqlservercode.blogspot.com/2006/09/five-ways-to-return-values-from-stored.html">Five Ways To Return Values From Stored Procedures</a></b><br />
A very old post that shows you five ways to return values from a stored proc<br />
<br />
01. <b><a href="http://sqlservercode.blogspot.com/2019/02/after-20-years-in-it-i-finally-discovered-this.html">After 20+ years in IT .. I finally discovered this...</a></b><br />
What can I say, read it and let me know if you knew this one....<br />
<br />
<br />
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-87808486715267848322019-10-30T06:54:00.000-07:002019-10-30T09:23:03.810-07:00SQLSTATE 4200 Error 666 and what to do.<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
<br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">This morning I was greeted by the following message from a job email</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><i>The maximum
system-generated unique value for a duplicate group was exceeded for index with
partition ID 72059165481762816. Dropping and re-creating the index may resolve
this; otherwise, use another clustering key. [SQLSTATE 42000] (Error 666)</i></span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">Almost Halloween? check!</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">Error 666? check!</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">Ever seen this error before? no!</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">The job has a step that inserts into a bunch of tables... </span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">The table in question had a clustered index that was created without </span><span style="font-family: "times new roman" , serif;">the UNIQUE property. When you create such an index, SQL Server will create a </span><span style="font-family: "times new roman" , serif;">uniqueifier</span><span style="font-family: "times new roman" , serif;"> internally</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">This part is from the </span><span style="font-family: "times new roman" , serif;"> </span><span style="font-family: "times new roman" , serif;">CSS SQL Server Engineers <a href="https://blogs.msdn.microsoft.com/psssql/2018/02/16/uniqueifier-considerations-and-error-666/">blog post</a></span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif;"><i>A uniqueifier (or uniquifier as reported by SQL Server internal tools) has been used in the engine for a long time (since SQL Server 7.0), and even being known to many, referenced in books and blogs, The SQL Server documentation clearly states that you will not see it exposed externally in the engine <a href="https://www.blogger.com/(https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-index-design-guide">(https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-index-design-guide</a>).</i></span><br />
<span style="font-family: "times new roman" , serif;"><i><br /></i></span>
<br />
<blockquote class="tr_bq">
<span style="font-family: "times new roman" , serif;"><i>"If the clustered index is not created with the UNIQUE property, the Database Engine automatically adds a 4-byte uniqueifier column to the table. When it is required, the Database Engine automatically adds a uniqueifier value to a row to make each key unique. This column and its values are used internally and cannot be seen or accessed by users."</i></span></blockquote>
<span style="font-family: "times new roman" , serif;"><i><br /></i></span>
<span style="font-family: "times new roman" , serif;"><i>While it´s unlikely that you will face an issue related with uniqueifiers, the SQL Server team has seen rare cases where customer reaches the uniqueifier limit of 2,147,483,648, generating error 666.</i></span><br />
<span style="font-family: "times new roman" , serif;"><i><br /></i></span>
<br />
<blockquote class="tr_bq">
<span style="font-family: "times new roman" , serif;"><i>Msg 666, Level 16, State 2, Line 1</i></span></blockquote>
<blockquote class="tr_bq">
<i><span style="font-family: "times new roman" , serif;"><br /></span><span style="font-family: "times new roman" , serif;">The maximum system-generated unique value for a duplicate group was exceeded for index with partition ID <PARTITIONID>. Dropping and re-creating the index may resolve this; otherwise, use another clustering key.</span></i></blockquote>
<br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">So I ran into this rare case :-(</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">How can you quickly find out what table and index name the error is complaining about?</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;">You can use the following query, just change the partitionid to match the one from your error message</span><br />
<span style="font-family: "times new roman" , serif; font-size: 12.0pt;"><br /></span>
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">SCHEMA_NAME</span>(o.schema_id) <span style="color: #008800; font-weight: bold;">as</span> SchemaName,
o.name <span style="color: #008800; font-weight: bold;">as</span> ObjectName,
i.name <span style="color: #008800; font-weight: bold;">as</span> IndexName,
p.partition_id <span style="color: #008800; font-weight: bold;">as</span> PartitionID
<span style="color: #008800; font-weight: bold;">FROM</span> sys.partitions p
<span style="color: #008800; font-weight: bold;">JOIN</span> sys.objects o <span style="color: #008800; font-weight: bold;">on</span> p.object_id = o.object_id
<span style="color: #008800; font-weight: bold;">JOIN</span> sys.indexes i <span style="color: #008800; font-weight: bold;">on</span> p.object_id = i.object_id
<span style="color: #008800; font-weight: bold;">WHERE</span> p.partition_id = <span style="color: #0000dd; font-weight: bold;">72059165481762816</span></pre>
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">After running the query, you will now have the schema name, the table name and the index name. That is all you need to find the index, you can now drop and recreate it</span><br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">In my case this table was not big at all... 5 million rows or so, but we do delete and insert a lot of data into this table many times a day.</span><br />
<span style="font-family: "times new roman" , serif;">Also we have rebuild jobs running, rebuild jobs do not reset the uniqifier (see also below about a change from the CSS </span><span style="font-family: "times new roman" , serif;">SQL Server Engineers</span><span style="font-family: "times new roman" , serif;">)</span><br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">To fix this, all I had to do was drop the index and recreate the index (after filling out tickets and testing it on a lower environment first). </span><br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">INDEX</span> [IX_IndexName] <span style="color: #008800; font-weight: bold;">ON</span> [SchemaName].TableName]
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> CLUSTERED <span style="color: #008800; font-weight: bold;">INDEX</span> [IX_IndexName] <span style="color: #008800; font-weight: bold;">ON</span> [SchemaName].[TableName]
(
Col1 <span style="color: #008800; font-weight: bold;">ASC</span>,
Col2 <span style="color: #008800; font-weight: bold;">ASC</span>,
Col3 <span style="color: #008800; font-weight: bold;">ASC</span>
) <span style="color: #008800; font-weight: bold;">ON</span> [<span style="color: #008800; font-weight: bold;">PRIMARY</span>]
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">After dropping and recreating the index.. the code that threw an error earlier did not throw an error anymore</span><br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">Since my table only had 5 million rows or so.. this was not a big deal and completed in seconds. If you have a large table you might have to wait or think of a different approach</span><br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;">If you want to know more, check out this post by the CSS SQL Server Engineers <a href="https://blogs.msdn.microsoft.com/psssql/2018/02/16/uniqueifier-considerations-and-error-666/">Uniqueifier considerations and error 666</a></span><br />
<br />
The interesting part is<br />
<br />
As of February 2018, the design goal for the storage engine is to not reset uniqueifiers during REBUILDs. As such, rebuild of the index ideally would not reset uniquifiers and issue would continue to occur, while inserting new data with a key value for which the uniquifiers were exhausted. But current engine behavior is different for one specific case, if you use the statement ALTER INDEX ALL ON <TABLE> REBUILD WITH (ONLINE = ON), it will reset the uniqueifiers (across all version starting SQL Server 2005 to SQL Server 2017).<br />
<br />
Important: This is something that is not documented and can change in future versions, so our recommendation is that you should review table design to avoid relying on it.<br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: "times new roman" , serif;"><br /></span><br />
<span style="font-family: "times new roman" , serif;"><br /></span>
<span style="font-family: times new roman, serif;">Edit.. it turns out I have seen this before and have even blogged about it </span><a href="http://sqlservercode.blogspot.com/2017/06/having-fun-with-maxed-out-uniqifiers-on.html">http://sqlservercode.blogspot.com/2017/06/having-fun-with-maxed-out-uniqifiers-on.html</a><br />
<br />
<br />
<br />Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-16771259.post-11774667996147805802019-06-11T07:02:00.001-07:002019-06-11T07:02:48.185-07:00Can adding an index make a non SARGable query SARGable?<br />
This question came up the other day from a co-worker, he said he couldn't change a query but was there a way of making the same query produce a better plan by doing something else perhaps (magic?)<br />
<br />
He said his query had a WHERE clause that looked like the following<br />
<br />
WHERE RIGHT(SomeColumn,3) = '333'<br />
<br />
I then asked if he could change the table, his answer was that he couldn't mess around with the current columns but he could add a column<br />
<br />
Ok, that got me thinking about a solution, let's see what I came up with<br />
<br />
<br />
First create the following table<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">USE tempdb
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> StagingData (SomeColumn <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">255</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span> )
<span style="color: #008800; font-weight: bold;">ALTER</span> <span style="color: #008800; font-weight: bold;">TABLE</span> dbo.StagingData <span style="color: #008800; font-weight: bold;">ADD</span> <span style="color: #008800; font-weight: bold;">CONSTRAINT</span>
PK_StagingData <span style="color: #008800; font-weight: bold;">PRIMARY</span> <span style="color: #008800; font-weight: bold;">KEY</span> CLUSTERED
(
SomeColumn
) <span style="color: #008800; font-weight: bold;">ON</span> [<span style="color: #008800; font-weight: bold;">PRIMARY</span>]
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;">
</pre>
We will create some fake data by appending a dot and a number between 100 and 999 to a GUID<br />
<br />
Let's insert one row so that you can see what the data will look like<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DECLARE</span> @guid uniqueidentifier
<span style="color: #008800; font-weight: bold;">SELECT</span> @guid = <span style="background-color: #fff0f0;">'DEADBEEF-DEAD-BEEF-DEAD-BEEF00000075'</span>
<span style="color: #008800; font-weight: bold;">INSERT</span> StagingData
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">200</span>),@guid) + <span style="background-color: #fff0f0;">'.100'</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData</pre>
<pre style="color: #333333; line-height: 16.25px;">
</pre>
<pre style="color: #333333; line-height: 16.25px;">
</pre>
Output<br />
<br />
SomeColumn<br />
--------------------------------<br />
DEADBEEF-DEAD-BEEF-DEAD-BEEF00000075.100<br />
<br />
<br />
<br />
<br />
Time to insert 999,999 rows<br />
<br />
Here is what the code looks like<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">INSERT</span> StagingData
<span style="color: #008800; font-weight: bold;">SELECT</span> top <span style="color: #0000dd; font-weight: bold;">999999</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">200</span>),NEWID())
+ <span style="background-color: #fff0f0;">'.'</span>
+ <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),s2.<span style="color: #007020;">number</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> master..SPT_VALUES s1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> master..SPT_VALUES s2
<span style="color: #008800; font-weight: bold;">WHERE</span> s1.<span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> s2.<span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">and</span> s1.<span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">between</span> <span style="color: #0000dd; font-weight: bold;">100</span> <span style="color: #008800; font-weight: bold;">and</span> <span style="color: #0000dd; font-weight: bold;">999</span>
<span style="color: #008800; font-weight: bold;">and</span> s2.<span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">between</span> <span style="color: #0000dd; font-weight: bold;">100</span> <span style="color: #008800; font-weight: bold;">and</span> <span style="color: #0000dd; font-weight: bold;">999</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<br />
With that completed we should now have one million rows<br />
<br />
<br />
If we run our query to look for rows where the last 3 characters are 333 we can see that we get a scan<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> SomeColumn <span style="color: #008800; font-weight: bold;">FROM</span> StagingData
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">3</span>) = <span style="background-color: #fff0f0;">'333'</span>
<span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">OFF</span>
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<br />
<br />
<br />
<br />
(900 rows affected)<br />
Table 'StagingData'. Scan count 1, logical reads 5404, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
<br />
We get 900 rows back and 5404 reads<br />
<br />
<br />
Here is what the execution plan looks like<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_4I_p92hmEyzoOBm8tvXrxmXYgaydCeS32GVoAdUgRGyQi17fwurftbsP8uovfx7eKk4ZfbAu6RXNRhCsl4g_Sj48kqm-5X7j_5YE3TuiHMpOZ1ZHoWqA1LqwTjR2HHwqlqzr/s1600/ClusteredIndexScan.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="230" data-original-width="592" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_4I_p92hmEyzoOBm8tvXrxmXYgaydCeS32GVoAdUgRGyQi17fwurftbsP8uovfx7eKk4ZfbAu6RXNRhCsl4g_Sj48kqm-5X7j_5YE3TuiHMpOZ1ZHoWqA1LqwTjR2HHwqlqzr/s640/ClusteredIndexScan.PNG" width="640" /></a></div>
<br />
<br />
<br />
<br />
<br />
If we always query for the last 3 characters, what we can do is add a computed column to the table that just contains the last 3 characters and then add a nonclustered index to that column<br />
<br />
That code looks like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">ALTER</span> <span style="color: #008800; font-weight: bold;">TABLE</span> StagingData <span style="color: #008800; font-weight: bold;">ADD</span> RightChar <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">3</span>)
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">INDEX</span> ix_RightChar <span style="color: #008800; font-weight: bold;">on</span> StagingData(RightChar)
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<br />
<br />
Now let's check what we get when we use this new column<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> SomeColumn <span style="color: #008800; font-weight: bold;">FROM</span> StagingData
<span style="color: #008800; font-weight: bold;">WHERE</span> RightChar = <span style="background-color: #fff0f0;">'333'</span>
<span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">OFF</span>
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<br />
<br />
(900 rows affected)<br />
Table 'StagingData'. Scan count 1, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
<br />
<br />
The reads went from 5404 to 10, that is a massive improvement, here is what the execution plan looks like<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8H0gB2b_GKuHDf5iBDSZVSoiE9_Ul9KkyGnJF9WbRXxTgu439LC2ZLA5coFusiDxzgmwVSpwGsNI7Gk48XgxApQyxv9jBknYbIM4nga3nRL0Q4c6Ad5KeOelJiMjT-d1QfJWM/s1600/CLusteredIndexSeekNewColumn.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="224" data-original-width="588" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8H0gB2b_GKuHDf5iBDSZVSoiE9_Ul9KkyGnJF9WbRXxTgu439LC2ZLA5coFusiDxzgmwVSpwGsNI7Gk48XgxApQyxv9jBknYbIM4nga3nRL0Q4c6Ad5KeOelJiMjT-d1QfJWM/s640/CLusteredIndexSeekNewColumn.PNG" width="640" /></a></div>
<br />
<br />
However there is a small problem.....<br />
<br />
We said we would not modify the query...<br />
<br />
What happens if we execute the same query from before? Can the SQL Server optimizer recognize that our new column and index is pretty much the same as the WHERE clause?<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> SomeColumn <span style="color: #008800; font-weight: bold;">FROM</span> StagingData
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">3</span>) = <span style="background-color: #fff0f0;">'333'</span>
<span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">OFF</span>
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><div style="color: black; font-family: "Times New Roman"; white-space: normal;">
(900 rows affected)</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
Table 'StagingData'. Scan count 1, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
Damn right, the optimizer can, , there it is, it uses the new index and column although we specify the original column..... (must be all that AI built in... (just kidding))</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
If you look at the execution plan, you can see it is indeed a seek</div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL2zI07P8KOKInmDKVA9pVRxIptCRTX97Ro2bih7-9pwtP45SuI_auIZodHwZt9mzojZPe7QipaCrmmJ2htu9C02H2Wsn9I6UM3rYjreMFjQ4xZc7iDiGObpUCbRt-dEwPK49G/s1600/ClusteredIndexSeek.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="199" data-original-width="594" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL2zI07P8KOKInmDKVA9pVRxIptCRTX97Ro2bih7-9pwtP45SuI_auIZodHwZt9mzojZPe7QipaCrmmJ2htu9C02H2Wsn9I6UM3rYjreMFjQ4xZc7iDiGObpUCbRt-dEwPK49G/s640/ClusteredIndexSeek.PNG" width="640" /></a></div>
<div style="color: black; font-family: "Times New Roman"; white-space: normal;">
</div>
</pre>
<br />
So there you have it.. sometimes, you can't change the query, you can't mess around with existing column but you can add a column to the table, in this case a technique like the following can be beneficial<br />
<br />
<br />
<br />
PS<br />
<br />
<a href="https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines">Betteridge's law of headlines</a> is an adage that states: "Any headline that ends in a question mark can be answered by the word no." It is named after Ian Betteridge, a British technology journalist who wrote about it in 2009<br />
<br />
In this case as you can plainly see...this is not true :-) The answer to "Can adding an index make a non SARGable query SARGable?" is clearly yes<br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-16771259.post-87812551505448716272019-04-24T06:13:00.000-07:002019-04-30T10:24:10.910-07:00How to count NULLS without using IS NULL in a WHERE clause<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
This came up the other day, someone wanted to know the percentage of NULL values in a column<br />
<br />
Then I said "I bet you I can run that query without using a NULL in the WHERE clause, as a matter of fact, I can run that query without a WHERE clause at all!!"<br />
<br />
The person then wanted to know more, so you know what that means.. it becomes a blog post :-)<br />
<br />
BTW, the PostgreSQL version of this blog post can be found here: <a href="https://denisgobo.blogspot.com/2019/04/a-quick-and-easy-way-to-count-percentage-of-nulls-without-a-where-clause-in-PostgreSQL.html">A quick and easy way to count the percentage of nulls without a where clause in PostgreSQL</a><br />
<br />
<br />
To get started, first create this table and verify you have 9 rows<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> foo(bar <span style="color: #007020;">int</span>)
<span style="color: #008800; font-weight: bold;">INSERT</span> foo <span style="color: #008800; font-weight: bold;">values</span>(<span style="color: #0000dd; font-weight: bold;">1</span>),(<span style="color: #008800; font-weight: bold;">null</span>),(<span style="color: #0000dd; font-weight: bold;">2</span>),(<span style="color: #0000dd; font-weight: bold;">3</span>),(<span style="color: #0000dd; font-weight: bold;">4</span>),
(<span style="color: #008800; font-weight: bold;">null</span>),(<span style="color: #0000dd; font-weight: bold;">5</span>),(<span style="color: #0000dd; font-weight: bold;">6</span>),(<span style="color: #0000dd; font-weight: bold;">7</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> foo</pre>
<br />
Here is what the output should be<br />
<br />
bar<br />
1<br />
NULL<br />
2<br />
3<br />
4<br />
NULL<br />
5<br />
6<br />
7<br />
<br />
To get the NULL values and NON NULL values, you can do something like this<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">as</span> CountAll <span style="color: #008800; font-weight: bold;">FROM</span> foo <span style="color: #008800; font-weight: bold;">WHERE</span> bar <span style="color: #008800; font-weight: bold;">IS</span> <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">as</span> CountAll <span style="color: #008800; font-weight: bold;">FROM</span> foo <span style="color: #008800; font-weight: bold;">WHERE</span> bar <span style="color: #008800; font-weight: bold;">IS</span> <span style="color: #008800; font-weight: bold;">NULL</span></pre>
<br />
However, there is another way<br />
<br />
Did you know that COUNT behaves differently if you use a column name compared to when you use *<br />
<br />
Take a look<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">as</span> CountAll,
<span style="color: #008800; font-weight: bold;">COUNT</span>(bar) <span style="color: #008800; font-weight: bold;">as</span> CountColumn
<span style="color: #008800; font-weight: bold;">FROM</span> foo</pre>
<br />
If you ran that query, the result is the following<br />
<br />
<b>CountAll CountColumn</b><br />
<b>----------- -----------</b><br />
<b>9 7</b><br />
<br />
Warning: Null value is eliminated by an aggregate or other SET operation.<br />
<br />
<br />
And did you notice the warning? That came from the count against the column<br />
<br />
Let's see what <a href="https://docs.microsoft.com/en-us/sql/t-sql/functions/count-transact-sql?view=sql-server-2017">Books On Line</a> has to say<br />
<br />
<br />
<i>COUNT(*) returns the number of items in a group. This includes NULL values and duplicates.</i><br />
<i><br /></i>
<i>COUNT(ALL expression) evaluates expression for each row in a group, and returns the number of nonnull values.</i><br />
<i><br /></i>
<i>COUNT(DISTINCT expression) evaluates expression for each row in a group, and returns the number of unique, nonnull values.</i><br />
<br />
This is indeed documented behavior<br />
<br />
So now, lets change our query to return the percentage of non null values in the column<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">as</span> CountAll,
<span style="color: #008800; font-weight: bold;">COUNT</span>(bar) <span style="color: #008800; font-weight: bold;">as</span> CountColumn,
(<span style="color: #008800; font-weight: bold;">COUNT</span>(bar)*<span style="color: #0000dd; font-weight: bold;">1</span>.<span style="color: #0000dd; font-weight: bold;">0</span>/<span style="color: #008800; font-weight: bold;">COUNT</span>(*))*<span style="color: #0000dd; font-weight: bold;">100</span> <span style="color: #008800; font-weight: bold;">as</span> PercentageOfNonNullValues
<span style="color: #008800; font-weight: bold;">FROM</span> foo</pre>
<br />
Here is the output<br />
<br />
CountAll CountColumn percentageOfNonNullValues<br />
----------- ----------- ---------------------------------------<br />
9 7 77.777777777700<br />
<br />
I just want to point out one thing, the reason I have this * 1.0 in the query<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">(<span style="color: #008800; font-weight: bold;">COUNT</span>(bar)<b>*<span style="color: #0000dd;">1</span>.<span style="color: #0000dd;">0</span></b>/<span style="color: #008800; font-weight: bold;">COUNT</span>(*))*<span style="color: #0000dd; font-weight: bold;">100</span></pre>
<br />
I am doing * 1.0 here because count returns an integer, so you will end up with integer math and the PercentageOfNonNullValues would be 0 instead of 77.7777...<br />
<br />
<br />
That's it for this short post.. hopefully you knew this, if not, then you know it now :-)<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-57344066419275025922019-04-14T06:53:00.003-07:002019-04-14T06:53:45.059-07:00How to check if an Extended Event session exists before dropping it<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
Are you still running profiler or have you transferred to using Extended Events? I use Extended Events almost exclusively now because it's so much easier compared to using profiler or trace from T-SQL. Not to mentioned you can capture more things<br />
<br />
<br />
The other day someone checked in some code and every now and then the build would fail with the error<br />
<br />
<b>Msg 15151, Level 16, State 19, Line 51</b><br />
<b>Cannot drop the event session 'ProcsExecutions', because it does not exist or you do not have permission.</b><br />
<br />
I decided to take a look at the code and saw what the problem was. I will recreate the code here and then show you what needs to be changed. This post will not go into what Extended Events are, you can look that up in the <a href="https://docs.microsoft.com/en-us/sql/relational-databases/extended-events/extended-events?view=sql-server-2017">SQL Server Extended Events documentation</a><br />
<br />
Start by creating the Extended Event session by executing the following T-SQL<br />
<br />
<pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span><span style="color: #333333;"> EVENT </span><span style="color: #008800; font-weight: bold;">SESSION</span><span style="color: #333333;"> ProcsExecutions </span><span style="color: #008800; font-weight: bold;">ON</span><span style="color: #333333;"> SERVER
</span><span style="color: #008800; font-weight: bold;">ADD</span><span style="color: #333333;"> EVENT sqlserver.rpc_completed(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
</span><span style="color: #008800; font-weight: bold;">WHERE</span><span style="color: #333333;"> ([sqlserver].[database_name]=N</span><span style="background-color: #fff0f0; color: #333333;">'Test'</span><span style="color: #333333;">)
),
</span><span style="color: #008800; font-weight: bold;">ADD</span><span style="color: #333333;"> EVENT sqlserver.rpc_starting(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
</span><span style="color: #008800; font-weight: bold;">WHERE</span><span style="color: #333333;"> ([sqlserver].[database_name]=N</span><span style="background-color: #fff0f0; color: #333333;">'Test'</span><span style="color: #333333;">)
)
</span></pre>
<br />
To start the Extended Event session from T-SQL, execute the following command<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = <span style="color: #008800; font-weight: bold;">START</span>; </pre>
<br />
<br />
Below is what the code looked like that was checked in.<br />
<br />
You can run it and it will execute without a problem<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">IF <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
<span style="color: #008800; font-weight: bold;">DROP</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">ADD</span> EVENT sqlserver.rpc_completed(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
<span style="color: #008800; font-weight: bold;">WHERE</span> ([sqlserver].[database_name]=N<span style="background-color: #fff0f0;">'Test'</span>)
),
<span style="color: #008800; font-weight: bold;">ADD</span> EVENT sqlserver.rpc_starting(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
<span style="color: #008800; font-weight: bold;">WHERE</span> ([sqlserver].[database_name]=N<span style="background-color: #fff0f0;">'Test'</span>)
)
<span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = <span style="color: #008800; font-weight: bold;">START</span>;
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<br />
However if you run the following command now<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"> <span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = STOP; </pre>
<br />
And then execute the same create Extended Event T-SQL Query again<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">IF <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
<span style="color: #008800; font-weight: bold;">DROP</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">ADD</span> EVENT sqlserver.rpc_completed(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
<span style="color: #008800; font-weight: bold;">WHERE</span> ([sqlserver].[database_name]=N<span style="background-color: #fff0f0;">'Test'</span>)
),
<span style="color: #008800; font-weight: bold;">ADD</span> EVENT sqlserver.rpc_starting(
ACTION(sqlos.task_time,sqlserver.client_app_name,
sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text)
<span style="color: #008800; font-weight: bold;">WHERE</span> ([sqlserver].[database_name]=N<span style="background-color: #fff0f0;">'Test'</span>)
)
<span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = <span style="color: #008800; font-weight: bold;">START</span>;
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<div>
<span style="color: #008800; font-weight: bold;"><br /></span></div>
<div>
<span style="color: #008800; font-weight: bold;"><br /></span></div>
You will get the error<br />
<br />
<b>Msg 25631, Level 16, State 1, Line 29</b><br />
<b>The event session, "ProcsExecutions", already exists. Choose a unique name for the event session.</b><br />
<br />
So why is that? There are 2 DMV that exist <b>sys.dm_xe_sessions</b> and <b>sys.server_event_sessions</b>. The DMV sys.dm_xe_sessions only returns a row for Extended Event sessions that are in the running state, the DMV sys.server_event_sessions will return a row even if the Extended Event session is not currently running<br />
<br />
Lets' take a look at what that looks like by running some queries and commands<br />
<br />
First we are going to stop the session and then query the <span style="color: #333333;">sys.dm_xe_sessions </span>DMV<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #888888;">--Stop the session if is running</span>
<span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = STOP;
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #888888;">-- this query returns only the running Extended Event sessions</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> dxs.name,
dxs.create_time,*
<span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">AS</span> dxs;</pre>
<br />
Output<br />
-----------------<br />
hkenginexesession<br />
system_health<br />
sp_server_diagnostics session<br />
telemetry_xevents<br />
<br />
As you can see our Extended Event session is not returned because it is not in a running state<br />
<br />
Now lets's query the <span style="color: #333333;">sys.server_event_sessions </span>DMV and check if our Extended Event session is returned<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #888888;">-- this query returns also Extended Event sessions that are not currently running</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> *
<span style="color: #008800; font-weight: bold;">FROM</span> sys.server_event_sessions </pre>
<br />
Output<br />
-----------------<br />
system_health<br />
AlwaysOn_health<br />
telemetry_xevents<br />
ProcsExecutions<br />
<br />
As you can see our Extended Event session is returned even though it is not in a running state<br />
<br />
If we now start the session again and then check the <span style="color: #333333;">sys.dm_xe_sessions </span>DMV, we will get back out session<br />
<br />
<pre style="line-height: 16.25px;"><span style="color: #888888;">-- start the session again</span><span style="color: #333333;">
</span><span style="color: #008800; font-weight: bold;">ALTER</span><span style="color: #333333;"> EVENT </span><span style="color: #008800; font-weight: bold;">SESSION</span><span style="color: #333333;"> ProcsExecutions
</span><span style="color: #008800; font-weight: bold;">ON</span><span style="color: #333333;"> SERVER
</span><span style="color: #008800; font-weight: bold;">STATE</span><span style="color: #333333;"> = </span><span style="color: #008800; font-weight: bold;">START</span><span style="color: #333333;">;
</span><span style="color: #008800; font-weight: bold;">GO</span><span style="color: #333333;">
</span><span style="color: #008800; font-weight: bold;">SELECT</span><span style="color: #333333;"> dxs.name,
dxs.create_time,*
</span><span style="color: #008800; font-weight: bold;">FROM</span><span style="color: #333333;"> sys.dm_xe_sessions </span><span style="color: #008800; font-weight: bold;">AS</span><span style="color: #333333;"> dxs;</span></pre>
<br />
Output<br />
-----------------<br />
hkenginexesession<br />
system_health<br />
sp_server_diagnostics session<br />
telemetry_xevents<br />
ProcsExecutions<br />
<br />
<br />
So now our Extended Event session is returned because it is in a running state<br />
<br />
Instead of this query to check for the existence<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">IF <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
<span style="color: #008800; font-weight: bold;">DROP</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<br />
What we really want is this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">IF <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.server_event_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
<span style="color: #008800; font-weight: bold;">DROP</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions <span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<br />
So basically we change the dmv from <span style="color: #333333;">sys.dm_xe_sessions </span>to <span style="color: #333333;">sys.server_event_sessions </span>in IF EXISTS check<br />
<br />
So it is a pretty easy change, just swap out the DMV<br />
<br />
<br />
<br />
If you want to stop a session if it is running, you can go ahead and implement something like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"> IF <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
<span style="color: #008800; font-weight: bold;">BEGIN</span>
PRINT <span style="background-color: #fff0f0;">'The Session Was Running'</span>
<span style="color: #008800; font-weight: bold;">ALTER</span> EVENT <span style="color: #008800; font-weight: bold;">SESSION</span> ProcsExecutions
<span style="color: #008800; font-weight: bold;">ON</span> SERVER
<span style="color: #008800; font-weight: bold;">STATE</span> = STOP;
<span style="color: #008800; font-weight: bold;">END</span>
IF <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">EXISTS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> name <span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_xe_sessions <span style="color: #008800; font-weight: bold;">WHERE</span> name = <span style="background-color: #fff0f0;">'ProcsExecutions'</span>)
PRINT <span style="background-color: #fff0f0;">'The Session is NOT Running'</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="background-color: #fff0f0;">
</span></pre>
<br />
That's all for this post, hopefully it will be useful to someone<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-75991610990395768172019-04-13T14:38:00.000-07:002019-04-13T14:39:44.511-07:00How to improve your tech skills<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Today we are going to look at how to improve your tech skills. This really is a continuation of the <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/stay-relevant-and-marketable" href="https://sqlservercode.blogspot.com/2019/03/stay-relevant-and-marketable-cloud-big-data-webinars.html">Stay relevant and marketable</a> post from a couple of weeks ago. Here are some things that you can do to improve your tech skills<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Attend usergroups</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Attend your local usergroup meetings, there is always some expert that comes to do presentations.<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Answer questions</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
I still think answering questions is one of the best ways to improve your skill. Join a QA site like <a data-mce-href="http://stackoverflow.com/questions" href="http://stackoverflow.com/questions">stackoverflow</a>, head on to a specialized site on stackexchange, here is a list of all of them <a href="http://stackexchange.com/sites">http://stackexchange.com/sites</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ9JnJnt84kyKPkQ-ZSDvVo3HzJDEfBIJFqDrd56O4YL2-0SR6dW4N5u__oN8MNUBrNscDXDsgroT-gJ57sCNFftH4e7_uX9fzsyo2h0ep6WaXwSiMcnt5K9bDaGV83RY8cGPm/s1600/StackExchange.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="628" data-original-width="1253" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ9JnJnt84kyKPkQ-ZSDvVo3HzJDEfBIJFqDrd56O4YL2-0SR6dW4N5u__oN8MNUBrNscDXDsgroT-gJ57sCNFftH4e7_uX9fzsyo2h0ep6WaXwSiMcnt5K9bDaGV83RY8cGPm/s640/StackExchange.PNG" width="640" /></a></div>
<br />
<br />
If you are not comfortable with answering yet or if you realize that the questions are too difficult, don't worry about, just start by lurking. What you will find out over time is that every month you will be able to answer more and more of these question. This is because the questions are pretty much the same but some little detail might be different. After a while you will notice that there will be very few questions that you won't be able to answer in your field of expertise<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Lunch and learns</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
No time you say to improve your skills, do you take lunch breaks? If so consider doing lunch and learns, get into a conference room, fire up the projector and then either look at code with the team, do design, watch videos, whatever floats your boat<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Get involved with an open source project</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
A good way to improve your skills is to get involved with an open source project. Pick a project download it, then pick it apart. Start reading through the code, notice how things are done, ask yourself why it was done that way. Would you do it the same way? If you pick a big enough project, there will be many contributors, can you tell that the code was put together or does it pretty much look like it was written by one person. Are standards followed, how many <a data-mce-href="http://www.amazon.com/gp/product/0201633612/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201633612&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0201633612/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201633612&linkCode=as2&tag=sql08-20">design patterns</a> are used<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Read books, read code, read blogs</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
There are many classic list of books that every programmer should read<br />
Here is just a small list that you can choose from, I grabbed this from <a data-mce-href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read" href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read">stackoverflow</a><br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<a data-mce-href="http://www.amazon.com/gp/product/0735619670/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735619670&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0735619670/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735619670&linkCode=as2&tag=sql08-20">Code Complete</a> (2nd edition) by Steve McConnell<br />
<a data-mce-href="http://www.amazon.com/gp/product/020161622X/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=020161622X&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/020161622X/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=020161622X&linkCode=as2&tag=sql08-20">The Pragmatic Programmer</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0201633612/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201633612&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0201633612/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201633612&linkCode=as2&tag=sql08-20">Design Patterns</a> by the Gang of Four<br />
<a data-mce-href="http://www.amazon.com/gp/product/0201485672/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201485672&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0201485672/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201485672&linkCode=as2&tag=sql08-20">Refactoring: Improving the Design of Existing Code</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0201835959/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201835959&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0201835959/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0201835959&linkCode=as2&tag=sql08-20">The Mythical Man Month</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0132350882/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0132350882&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0132350882/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0132350882&linkCode=as2&tag=sql08-20">Clean Code: A Handbook of Agile Software Craftsmanship</a> by Robert C. Martin<br />
<a data-mce-href="http://www.amazon.com/gp/product/0735611319/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735611319&linkCode=as2&tag=sql08-20http://www.amazon.com/gp/product/0735611319/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735611319&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0735611319/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735611319&linkCode=as2&tag=sql08-20http://www.amazon.com/gp/product/0735611319/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0735611319&linkCode=as2&tag=sql08-20">CODE</a> by Charles Petzold<br />
<a data-mce-href="http://www.amazon.com/gp/product/0131177052/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0131177052&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0131177052/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0131177052&linkCode=as2&tag=sql08-20">Working Effectively with Legacy Code</a> by Michael C. Feathers<br />
<a data-mce-href="http://www.amazon.com/gp/product/0932633439/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0932633439&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0932633439/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0932633439&linkCode=as2&tag=sql08-20">Peopleware</a> by Demarco and Lister<br />
<a data-mce-href="http://www.amazon.com/gp/product/1430219483/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1430219483&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/1430219483/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1430219483&linkCode=as2&tag=sql08-20">Coders at Work</a> by Peter Seibel<br />
<a data-mce-href="http://www.amazon.com/gp/product/0321127420/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321127420&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0321127420/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321127420&linkCode=as2&tag=sql08-20">Patterns of Enterprise Application Architecture</a> by Martin Fowler<br />
<a data-mce-href="http://www.amazon.com/gp/product/0321146530/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321146530&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0321146530/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321146530&linkCode=as2&tag=sql08-20">Test-Driven Development: By Example</a> by Kent Beck<br />
<a data-mce-href="http://www.amazon.com/gp/product/097451408X/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=097451408X&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/097451408X/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=097451408X&linkCode=as2&tag=sql08-20">Practices of an Agile Developer</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0321344758/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321344758&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0321344758/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321344758&linkCode=as2&tag=sql08-20">Don't Make Me Think</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0135974445/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0135974445&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0135974445/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0135974445&linkCode=as2&tag=sql08-20">Agile Software Development, Principles, Patterns, and Practices</a> by Robert C. Martin<br />
<a data-mce-href="http://www.amazon.com/gp/product/0321125215/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321125215&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0321125215/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0321125215&linkCode=as2&tag=sql08-20">Domain Driven Designs</a> by Eric Evans<br />
<a data-mce-href="http://www.amazon.com/gp/product/0465067107/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0465067107&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0465067107/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0465067107&linkCode=as2&tag=sql08-20">The Design of Everyday Things</a> by Donald Norman<br />
<a data-mce-href="http://www.amazon.com/gp/product/0596517742/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0596517742&linkCode=as2&tag=sql08-20http://www.amazon.com/gp/product/0596517742/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0596517742&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0596517742/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0596517742&linkCode=as2&tag=sql08-20http://www.amazon.com/gp/product/0596517742/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0596517742&linkCode=as2&tag=sql08-20">JavaScript - The Good Parts</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0578012812/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0578012812&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0578012812/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0578012812&linkCode=as2&tag=sql08-20">Getting Real by 37 Signals</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0470229055/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0470229055&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0470229055/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0470229055&linkCode=as2&tag=sql08-20">The Annotated Turing</a><br />
<a data-mce-href="http://www.amazon.com/gp/product/0131857258/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0131857258&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0131857258/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0131857258&linkCode=as2&tag=sql08-20">Agile Principles, Patterns, and Practices in C#</a> by Robert C. Martin<br />
<a data-mce-href="http://www.amazon.com/gp/product/B00008RWB6/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00008RWB6&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/B00008RWB6/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00008RWB6&linkCode=as2&tag=sql08-20">The Soul of a New Machine</a> by Tracy Kidder<br />
<a data-mce-href="http://www.amazon.com/gp/product/0143114948/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0143114948&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0143114948/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0143114948&linkCode=as2&tag=sql08-20">Here Comes Everybody: The Power of Organizing Without Organizations</a> by Clay Shirky<br />
<a data-mce-href="http://www.amazon.com/gp/product/0977616673/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0977616673&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0977616673/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0977616673&linkCode=as2&tag=sql08-20">Pragmatic Unit Testing in C# with NUnit</a> by Andy Hunt and Dave Thomas with Matt Hargett<br />
<a data-mce-href="http://www.amazon.com/gp/product/0307463745/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0307463745&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/0307463745/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0307463745&linkCode=as2&tag=sql08-20">Rework</a> by Jason Freid and DHH<br />
<a data-mce-href="http://www.amazon.com/gp/product/1935182021/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1935182021&linkCode=as2&tag=sql08-20" href="http://www.amazon.com/gp/product/1935182021/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1935182021&linkCode=as2&tag=sql08-20">JUnit in Action</a></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
Reading code is also a good way to improve your skills, head over to the frameworks you use the most and start digging around in the API, look at the example code.<br />
Read blogs of subject expert, study their code and techniques, if something is not clear don't hesitate to leave a comment asking for some info or further explanation<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Practice by doing katas</h2>
<div>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">If you have ever done Karate you will know what a kata is, it is basically the practice of forms. A kata, or code kata, is defined as an exercise in programming which helps hone your skills through practice and repetition. Dave Thomas, started this movement for programming. You can find a list of awesome katas here: </span><a href="https://github.com/gamontal/awesome-katas">https://github.com/gamontal/awesome-katas</a><br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Blog</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
I found that blogging has been very good for my tech skills. It keeps me sharp and since I blog about new things it keeps my skill set up to date. When blogging, your readers will tell you when the code is wrong, so you have to make sure everything is tested and will run as shown in the post. Since you will have to do some research when writing these blog posts, your skills will improve and expand.<br />
An added bonus is that I have a code library that I can access anytime I want.<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Write a book</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
If you are a masochistic type of person then I recommend you write a book, almost everybody in the tech world that I know swore that they would never write a book again when they were done.......and yet they did. In order to write a book you have to spend a LOT of time doing research, making sure your code is correct and much more. Once you are done with this if you were not a subject expert you will be now. The worst part of writing a book is the initial feedback you get pointing out all your mistakes, if you are not thick skinned this could become a problem.<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Listen to podcast, watch webinars</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
I get a lot of my tech info from podcasts, I like it better than listening to music at times and it makes the commute or run more enjoyable. The benefit is that you will learn something, you also might hear about some new shiny thing and then you will want to check it out when you get to the computer. There are many things I have learned from podcast, I also look forward to the next episode<br />
<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-26783651102238767772019-03-20T06:32:00.000-07:002019-03-20T06:32:31.618-07:00Some numbers that you will know by heart if you have been working with SQL Server for a while<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
This is just a quick and fun post.<br />
<br />
I was troubleshooting a deadlock the other day and it got me thinking.... I know the number 1205 by heart and know it is associated to a deadlock. What other numbers are there that you can associate to an event or object or limitation. For example 32767 will be known by a lot of people as the database id of the ResourceDb, master is 1, msdb is 4 etc etc.<br />
<br />
So below is a list of numbers I thought of<br />
<br />
Leave me a comment with any numbers that you know by heart<br />
<br />
BTW I didn't do the limits for int, smallint etc etc, those are the same in all programming languages...so not unique to SQL Server<br />
<br />
<br />
<b>-1</b><br />
You use -1 with DBCC TRACESTATUS to see what trace flags are enabled on your system<br />
<br />
For example on a brand new instance, I turned on these 3 trace flags, then when I check tracestatus, I get them back in the output<br />
<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">DBCC TRACEON (<span style="color: #0000dd; font-weight: bold;">3605</span>,<span style="color: #0000dd; font-weight: bold;">1204</span>,<span style="color: #0000dd; font-weight: bold;">1222</span>,-<span style="color: #0000dd; font-weight: bold;">1</span>)
DBCC TRACESTATUS(-<span style="color: #0000dd; font-weight: bold;">1</span>)</pre>
<br />
<br />
TraceFlag<span style="white-space: pre;"> </span>Status<span style="white-space: pre;"> </span>Global<span style="white-space: pre;"> </span>Session<br />
1204<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>0<br />
1222<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>0<br />
3605<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>1<span style="white-space: pre;"> </span>0<br />
<br />
<br />
<br />
<br />
<b>1</b><br />
You can only have 1 clustered index per table. This is also a favorite interview question, asking people to explain why there can only be 1 clustered index<br />
<br />
<br />
<b>3</b><br />
The smallest fraction second number in a datetime datatype is 3<br />
<br />
Fractions of a seconds are rounded to increments of .000, .003, or .007 seconds<br />
<br />
<br />
This means the value after 000 midnight is .003 seconds<br />
<br />
Take a look at this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DECLARE</span> @d DATETIME = <span style="background-color: #fff0f0;">'2019-03-19 23:59:59.997'</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @d <span style="color: #008800; font-weight: bold;">AS</span> orig,
dateadd(ms,<span style="color: #0000dd; font-weight: bold;">1</span>,@d) <span style="color: #008800; font-weight: bold;">AS</span> orig1ms,
dateadd(ms,<span style="color: #0000dd; font-weight: bold;">2</span>,@d) <span style="color: #008800; font-weight: bold;">AS</span> orig2ms,
dateadd(ms,<span style="color: #0000dd; font-weight: bold;">3</span>,@d) <span style="color: #008800; font-weight: bold;">AS</span> orig3ms,
dateadd(ms,<span style="color: #0000dd; font-weight: bold;">4</span>,@d) <span style="color: #008800; font-weight: bold;">AS</span> orig4ms,
dateadd(ms,<span style="color: #0000dd; font-weight: bold;">5</span>,@d) <span style="color: #008800; font-weight: bold;">AS</span> orig5ms</pre>
<br />
<br />
Output<br />
<br />
2019-03-19 23:59:59.997<span style="white-space: pre;"> </span><br />
2019-03-19 23:59:59.997<span style="white-space: pre;"> </span><br />
2019-03-20 00:00:00.000<span style="white-space: pre;"> </span><br />
2019-03-20 00:00:00.000<span style="white-space: pre;"> </span><br />
2019-03-20 00:00:00.000<span style="white-space: pre;"> </span><br />
<b>2019-03-20 00:00:00.003</b><br />
<br />
This is also the reason you will see datetimes in queries ending in the following values for the time portion '23:59:59.997'. It will mostly be used with BETWEEN<br />
<br />
For example<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> ...
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">WHERE</span> SomeDAte <span style="color: #008800; font-weight: bold;">BETWEEN</span> <span style="background-color: #fff0f0;">'2019-03-19'</span> <span style="color: #008800; font-weight: bold;">and</span> <span style="background-color: #fff0f0;">'2019-03-19 23:59:59.997'</span></pre>
<br />
WHICH of course is the same as the query below<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> ...
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">WHERE</span> SomeDAte >=<span style="background-color: #fff0f0;">'2019-03-19'</span>
<span style="color: #008800; font-weight: bold;">AND</span> SomeDAte < <span style="background-color: #fff0f0;">'2019-03-20'</span></pre>
<br />
But it's less typing to use between :-)<br />
<br />
<br />
Another one with the number 3 is the /3GB flag you could set in the boot.ini file. In that case if you had a 32 bit 4 GB system, SQL Server could now use 3GB instead of only 2GB.... oh the good old times :-)<br />
<br />
<br />
<b>10</b><br />
STATS = 10<br />
<br />
When you script out a BACKUP or RESTORE command, it will by default use STATS =10, so every 10% you will get a message like below<br />
<br />
10 percent processed.<br />
20 percent processed.<br />
30 percent processed.<br />
40 percent processed.<br />
50 percent processed.<br />
<br />
For big databases, I like to use STATS = 1<br />
<br />
<br />
<br />
<b>15</b><br />
If you have been using SQL Server for a while, you might see this in the error log<br />
<br />
SQL Server has encountered 1 occurrence(s) of I/O requests taking longer than 15 seconds to complete on file [D:\SomeFilename.ldf] in database<br />
The OS file handle is 0x0000000000000950. The offset of the latest long I/O is: 0x000000545eb200<br />
<br />
There are several reasons why this might happen<br />
<br />
1. SQL Server is spawning more I/O requests than what the I/O disk subsystem could handle.<br />
<br />
2 . There could be an issue with the I/O subsystem (or) driver/firmware issue (or) Misconfiguration in the I/O Subsystem (or) Compression is turned on, so the Disks are performing very slow and thus SQL Server is affected by this<br />
<br />
3. Some other process on the system is saturating the disks with I/O requests. Common application includes AV Scan,System Backup Etc.<br />
<br />
<br />
<br />
<b>50</b><br />
Session ids which are smaller than 50 are system... You would filter this out from sp_who2 to get all the user generated sessions (not always true I have seen mirroring spids being between 51 and 70 on one my servers)<br />
<br />
These days you would use is_user_process instead<br />
<br />
So instead of this query<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> *
<span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_exec_sessions <span style="color: #008800; font-weight: bold;">AS</span> es <span style="color: #008800; font-weight: bold;">WITH</span> (NOLOCK)
<span style="color: #008800; font-weight: bold;">WHERE</span> es.session_id > <span style="color: #0000dd; font-weight: bold;">50</span></pre>
<br />
You would use this one<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> *
<span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_exec_sessions <span style="color: #008800; font-weight: bold;">AS</span> es <span style="color: #008800; font-weight: bold;">WITH</span> (NOLOCK)
<span style="color: #008800; font-weight: bold;">WHERE</span> es.is_user_process = <span style="color: #0000dd; font-weight: bold;">1</span></pre>
<br />
<br />
<br />
<b>99.999</b><br />
The five nines.. everyone knows this number... a 99.999% uptime certification means that the service or application will only be down for approximately five minutes and 15 seconds every year.<br />
<br />
<b>100</b><br />
The default for MAXRECURSION in a recursive CTE<br />
<br />
<br />
<b>128</b><br />
Identifier length (name of table, column etc etc)<br />
<br />
<br />
128 is plenty, I still remember some FoxPro databases where the length could not exceed 8, then you would end up with Addrln1 etc etc<br />
<br />
<br />
Here is a repo script that will attempt to create a table where the name is 130 characters in length<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DECLARE</span> @Ident <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">150</span>) = REPLICATE(<span style="background-color: #fff0f0;">'A'</span>, <span style="color: #0000dd; font-weight: bold;">150</span>)
<span style="color: #008800; font-weight: bold;">DECLARE</span> @<span style="color: #008800; font-weight: bold;">sql</span> <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">500</span>) = <span style="background-color: #fff0f0;">'create table '</span> + @Ident +<span style="background-color: #fff0f0;">'(id int)'</span>
<span style="color: #008800; font-weight: bold;">EXEC</span>( @<span style="color: #008800; font-weight: bold;">sql</span> )</pre>
<br />
And it blows up with the following error<br />
Msg 103, Level 15, State 4, Line 1<br />
The identifier that starts with 'AAAA.....AAA' is too long. Maximum length is 128.<br />
<br />
<br />
<br />
<b>300</b><br />
<span style="background-color: white; color: #333333; font-family: "Open Sans", sans-serif; font-size: 14px;">Page Life Expectancy is 300 seconds, meaning SQL Server can only keep those pages in memory for 300 seconds after reading them. This number is quoted all over the place that indicates you have issues if you fall below that. Is the number 300 still correct? Start here </span><span style="color: #333333; font-family: Open Sans, sans-serif;"><span style="font-size: 14px;"><a href="https://www.sqlskills.com/blogs/paul/page-life-expectancy-isnt-what-you-think/">https://www.sqlskills.com/blogs/paul/page-life-expectancy-isnt-what-you-think/</a></span></span><br />
<span style="color: #333333; font-family: Open Sans, sans-serif;"><br /></span>
<br />
<b>900</b><br />
900 bytes for a clustered index. But then again if you have such a wide clustered index and several nonclustered indexes... good luck!<br />
<br />
<br />
<b>999</b><br />
Nonclustered indexes you can have per table<br />
I believe this number used to be 249 or 254 back in the day... but I guess it changed after that monstrosity sharepoint came into existence<br />
<br />
<br />
<b>1,000</b><br />
Ah yes, who doesn't remember this number. It usually starts with someone saying that they don't see any job history for the job they created on the new server<br />
<br />
Hmmm, you already know the answer don't you?<br />
You go and open up SQL Agent-->Properties-->History<br />
And what do you see?<br />
<br />
Maximum job history log size: 1000<br />
Maximum job history rows per job: 100<br />
<br />
<br />
Ah yes..those nasty defaults<br />
<br />
Or someone was evil and executed the proc sp_purge_jobhistory for your job :-)<br />
<br />
<br />
<b>1,205</b><br />
Transaction (Process ID %d) was deadlocked on %.*ls resources with another process and has been chosen as the deadlock victim. Rerun the transaction.<br />
<br />
<br />
<b>1,222</b><br />
Use this trace flag to return the resources and types of locks that are participating in a deadlock and also the current command affected<br />
<br />
<b>1,433</b><br />
The default port SQL Server is listening on<br />
<br />
<b>1,700</b><br />
You can have 1,700 bytes for a nonclustered index.<br />
<br />
<br />
<b>2,100</b><br />
Parameters per stored procedure or user-defined function<br />
<br />
Tried that one as well...<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">declare</span> @d <span style="color: #007020;">varchar</span>(<span style="color: #008800; font-weight: bold;">max</span>) = <span style="background-color: #fff0f0;">'create procedure prtest '</span>
;<span style="color: #008800; font-weight: bold;">with</span> cte <span style="color: #008800; font-weight: bold;">as</span> (
<span style="color: #008800; font-weight: bold;">select</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">from</span> master..spt_values
<span style="color: #008800; font-weight: bold;">where</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span>
<span style="color: #008800; font-weight: bold;">union</span>
<span style="color: #008800; font-weight: bold;">select</span> <span style="color: #007020;">number</span> + <span style="color: #0000dd; font-weight: bold;">2048</span> <span style="color: #008800; font-weight: bold;">from</span> master..spt_values
<span style="color: #008800; font-weight: bold;">where</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span>
)
<span style="color: #008800; font-weight: bold;">select</span> top <span style="color: #0000dd; font-weight: bold;">2101</span> @d += <span style="background-color: #fff0f0;">'@i'</span> + <span style="color: #008800; font-weight: bold;">convert</span>(<span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),<span style="color: #007020;">number</span>) + <span style="background-color: #fff0f0;">' int ,'</span>
<span style="color: #008800; font-weight: bold;">from</span> cte
<span style="color: #008800; font-weight: bold;">select</span> @d = <span style="color: #008800; font-weight: bold;">left</span>(@d, len(@d) -<span style="color: #0000dd; font-weight: bold;">1</span>) + <span style="background-color: #fff0f0;">'as select 1 as Test'</span>
<span style="color: #008800; font-weight: bold;">exec</span>(@d)</pre>
<br />
<br />
And here is the error<br />
<br />
Msg 180, Level 15, State 1, Procedure prtest, Line 1<br />
There are too many parameters in this CREATE PROCEDURE statement. The maximum number is 2100.<br />
<br />
<br />
<b>3,226<span style="white-space: pre;"> </span></b><br />
Oh your errorlog is full of messages like these?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjikEsYLqFo9ScWiihOjFMxWQ9MYDFJbxvB_JTs5ZuGRga9rzycHvLgYI3fU7avV7Ps0Off3GQvaz8udAny6C9Dln2ELiFmMpBwf7SPDl9PmWShO0dvbauGPlmaIbM1e5ut7elU/s1600/BAckupsInErrorLog.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="56" data-original-width="813" height="44" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjikEsYLqFo9ScWiihOjFMxWQ9MYDFJbxvB_JTs5ZuGRga9rzycHvLgYI3fU7avV7Ps0Off3GQvaz8udAny6C9Dln2ELiFmMpBwf7SPDl9PmWShO0dvbauGPlmaIbM1e5ut7elU/s640/BAckupsInErrorLog.PNG" width="640" /></a></div>
<br />
Those are not really errors are they?<br />
<br />
To stop logging all of your backup success entries to the error log, use traceflag 3226<br />
<br />
<div>
<br /></div>
<b>3,605</b><br />
Like I showed in the section for number -1, you would use traceflag 3605 alongside traceflags 1204 and 1222 to send deadlock information to the error log<br />
<br />
<b>4,096</b><br />
Columns per SELECT statement. Really who has such a query?<br />
<br />
Hmm, I just had to try that out<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">declare</span> @d <span style="color: #007020;">varchar</span>(<span style="color: #008800; font-weight: bold;">max</span>) = <span style="background-color: #fff0f0;">'select top 1 '</span>
;<span style="color: #008800; font-weight: bold;">with</span> cte <span style="color: #008800; font-weight: bold;">as</span> (
<span style="color: #008800; font-weight: bold;">select</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">from</span> master..spt_values
<span style="color: #008800; font-weight: bold;">where</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span>
<span style="color: #008800; font-weight: bold;">union</span>
<span style="color: #008800; font-weight: bold;">select</span> <span style="color: #007020;">number</span> + <span style="color: #0000dd; font-weight: bold;">2048</span> <span style="color: #008800; font-weight: bold;">from</span> master..spt_values
<span style="color: #008800; font-weight: bold;">where</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span>
<span style="color: #008800; font-weight: bold;">union</span> <span style="color: #008800; font-weight: bold;">all</span>
<span style="color: #008800; font-weight: bold;">select</span> <span style="color: #0000dd; font-weight: bold;">4096</span>)
<span style="color: #008800; font-weight: bold;">select</span> @d += <span style="background-color: #fff0f0;">'name as ['</span> + <span style="color: #008800; font-weight: bold;">convert</span>(<span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),<span style="color: #007020;">number</span>) + <span style="background-color: #fff0f0;">'] ,'</span>
<span style="color: #008800; font-weight: bold;">from</span> cte
<span style="color: #008800; font-weight: bold;">select</span> @d = <span style="color: #008800; font-weight: bold;">left</span>(@d, len(@d) -<span style="color: #0000dd; font-weight: bold;">1</span>) + <span style="background-color: #fff0f0;">'from sys.objects'</span>
<span style="color: #008800; font-weight: bold;">exec</span>(@d)</pre>
<br />
(1 row(s) affected)<br />
Msg 1056, Level 15, State 1, Line 1<br />
The number of elements in the select list exceeds the maximum allowed number of 4096 elements.<br />
<br />
<br />
Also 4096 is the default network packet size<br />
<br />
<br />
<br />
<b>4,199</b><span style="white-space: pre;"> </span><br />
Traceflag 4199 Enables query optimizer (QO) fixes released in SQL Server Cumulative Updates and Service Packs. See also the hint 'ENABLE_QUERY_OPTIMIZER_HOTFIXES' from SQL Server 2016 SP1 onwards<br />
<br />
<br />
<br />
<b>8,060</b><br />
Bytes per page<br />
The number of bytes a page can hold.. and also the number of bytes a row can hold (not taking into account row overflow data types)<br />
<br />
<br />
<b>15,000</b><br />
Partitions per partitioned table or index<br />
I think this used to be either 999 or 1000...don't remember exactly<br />
<br />
<br />
<b>32,767</b><br />
This is database id of the ResourceDbUnknownnoreply@blogger.com5tag:blogger.com,1999:blog-16771259.post-47808877065557155692019-03-18T06:57:00.000-07:002019-03-18T07:06:59.702-07:00Stay relevant and marketable<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
<div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">It has been a while since I wrote some of my best practices posts. I decided to revisit these posts again to see if anything has changed, I also wanted to see if I could add some additional info.</span></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br />
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Whenever I interview people for a DB position, I always ask what the latest version is that they have used. I will also ask if they have used the version that is in beta now. More often than not I will get an answer that they are still running something that is two versions behind. Then I ask if they have installed the latest and greatest on their home computer. The answer to that question is usually no.<br />
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
This to me is crazy, surely you can't be in this field just for the money, where is the passion for discovering new things? Imagine you are a person who makes tables, after a while you will become a master and there is not much more for you to learn. The curse and the blessing of technology is that it is changing, and it is changing rapidly. If you don't invest time after work, before work and over the weekend to discover new things, play with the newest versions and sharpen your skill you will become obsolete, there are many people like that, they fall apart during the interview process.<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
But I have no time to do all this additional work</h2>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
People will complain that they don't have enough time to do these additional things. Here are some things you can do if you are short on time. If commuting by public transportation read a book or download the latest papers about the newest versions of the product and read them. If you workout try listening to podcast while doing your aerobic exercises. Perhaps you can set the speed on your player to be 30% faster, this way you can get more podcasts in the same amount of time.<br />
<br />
Ask yourself what will help you advance, having up to date skill or being up to date with the latest episodes of Billions, Narcos or American Gods? Another option is to watch the shows on the train on a tablet and then do the tech stuff at home.</div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Attend an launch event or go to your local usergroup meeting, there are usually sessions on the latest and greatest versions of the software. Youtube also has tons of free sessions.<br />
<br />
Here are the <b>Amazon AWS re:Invent 2018</b> breakout sessions <a href="https://www.youtube.com/user/AmazonWebServices/playlists?shelf_id=33&view=50&sort=dd">https://www.youtube.com/user/AmazonWebServices/playlists?shelf_id=33&view=50&sort=dd</a><br />
<br />
The <b>Microsoft Ignite </b>sessions can be found here:<br />
<a href="https://www.youtube.com/channel/UCrhJmfAGQ5K81XQ8_od1iTg">https://www.youtube.com/channel/UCrhJmfAGQ5K81XQ8_od1iTg</a><br />
<br />
The <b>Google Developer </b>sessions can be found here:<br />
<a href="https://www.youtube.com/user/GoogleDevelopers">https://www.youtube.com/user/GoogleDevelopers</a><br />
<br />
<b>Database related sessions: </b><a href="https://sqlservercode.blogspot.com/2018/05/azure-sql-data-warehouse-azure-sql.html">Azure SQL Data Warehouse, Azure SQL Database and SQL Server sessions from the Build 2018 conference</a><br />
<br />
Do you eat lunch? If so, instead of going out for lunch, bring your lunch to the office. While eating your lunch at your desk, watch some of the sessions listed above or read some documentation or books about technologies that you are interested in. If you prefer to read and you want to learn about SQl Server Execution Plans? Head on over to Hugo Kornelis' <a href="https://sqlserverfast.com/epr/">SQL Server Execution Plan Reference</a> site<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Step outside your comfort zone</h2>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Try out some other things, become a polyglot programmer. If you are a Java developer, give Scala or Clojure a try. If you are a .NET developer then try out F#, IronPython or Boo. If you are a SQL Server guy why not start playing around with Oracle, PostgreSQL or perhaps even a flavor of NoSQL, take a look at MongoDB, CouchDB, Cassandra and other solutions.<br />
<br />
Have you looked at Big Data? This is already getting big and it will only get bigger. Ever heard of Hadoop? No, heard of facebook? Sure you have, guess what, facebook claims to have the biggest Hadoop cluster, It is over 100 Petabytes and it grows by about half a Petabyte per day, and you thought your database was big :-)<br />
<br />
Trends are cyclical, every 10 years or so something new and big comes along. In the late 90s this was data warehousing, OLAP cubes, dimensions, fact tables. Every company these days does some sort of data warehousing. Now it is big data, data science, AI and machine learning that is new and shiny. Take a look at some of that stuff<br />
<br />
<br /></div>
<div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Finally have you looked at the cloud yet? If you have not... I beg you to take a look. </div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
If you think that you need to have money to get started, this is not true</div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
You can start with the free tiers to get some experience. All 3 major could providers offer free tiers</div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
Here are the links to these free tiers in order of cloud vendor by market share</div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<b>Amazon Webservices</b></div>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><a href="https://aws.amazon.com/free/">https://aws.amazon.com/free/</a></span><br />
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><br /></span>
<br />
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<b>Microsoft Azure</b></div>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><a href="https://azure.microsoft.com/en-us/free/">https://azure.microsoft.com/en-us/free/</a></span><br />
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<b>Google Cloud </b></div>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><a href="https://cloud.google.com/free/">https://cloud.google.com/free/</a></span><br />
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><br /></span>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"><br /></span>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">That's it for this post.... happy learning.....</span></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: georgia, "times new roman", "bitstream charter", times, serif; font-size: 16px;">
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-59040987116876879962019-03-16T08:17:00.000-07:002019-03-18T06:19:39.886-07:00Use sys.configurations to find features that are enabled but perhaps not used<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">It has been a while since I wrote some of my best practices posts. I decided to revisit these posts again to see if anything has changed, I also wanted to see if I could add some additional info.</span><br />
<div style="background-color: white;">
</div>
<br style="background-color: white;" />
<br style="background-color: white;" />
<span style="background-color: white;">Today we are going to look at</span><span style="background-color: white;"> </span>servers where everything is installed and enabled. Before we start this post let's look back in time a little. Before SQL Server 2005 came out when you installed SQL Server pretty much everything was turned on by default. This of course widened the attack vector against the database servers. With SQL Server 2005 pretty much everything is turned off and you have to turn the features on if you want to use them. Now sometimes some admins will just turn everything on because that way they don't have to deal with this later, these are also the same kind of people who insist that the account needs to be db_owner otherwise their code won't work.<br />
<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
To see what these features are and if they are turned off, you can use the following query.<br />
<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> name, value,value_in_use
<span style="color: #008800; font-weight: bold;">FROM</span> sys.configurations
<span style="color: #008800; font-weight: bold;">WHERE</span> name <span style="color: #008800; font-weight: bold;">IN</span> (
<span style="background-color: #fff0f0;">'Agent XPs'</span>,
<span style="background-color: #fff0f0;">'SQL Mail XPs'</span>,
<span style="background-color: #fff0f0;">'Database Mail XPs'</span>,
<span style="background-color: #fff0f0;">'SMO and DMO XPs'</span>,
<span style="background-color: #fff0f0;">'Ole Automation Procedures'</span>,
<span style="background-color: #fff0f0;">'SQL Mail XPs'</span>,
<span style="background-color: #fff0f0;">'external scripts enabled'</span>,
<span style="background-color: #fff0f0;">'Web Assistant Procedures'</span>,
<span style="background-color: #fff0f0;">'xp_cmdshell'</span>,
<span style="background-color: #fff0f0;">'Ad Hoc Distributed Queries'</span>,
<span style="background-color: #fff0f0;">'hadoop connectivity'</span>,
<span style="background-color: #fff0f0;">'polybase enabled'</span>,
<span style="background-color: #fff0f0;">'Replication XPs'</span>,
<span style="background-color: #fff0f0;">'clr enabled'</span>)</pre>
</pre>
<br />
Here is what the output looks like on my laptop<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXPDjkgt_7Xvbrl_yii_SApJEdbdlA1vlMuzBmZi-Qx4EdIK6tXxV_Hb3lNqaYeRAOc2ko80N9SURRWWfAUMfypIlZkW74kFAk7EElOKDk76u7Q1l4R199EX6sHkfLOCKtrQEz/s1600/sys.configurations.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="sys.configurations output" border="0" data-original-height="357" data-original-width="426" height="335" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXPDjkgt_7Xvbrl_yii_SApJEdbdlA1vlMuzBmZi-Qx4EdIK6tXxV_Hb3lNqaYeRAOc2ko80N9SURRWWfAUMfypIlZkW74kFAk7EElOKDk76u7Q1l4R199EX6sHkfLOCKtrQEz/s400/sys.configurations.PNG" title="sys.configurations" width="400" /></a></div>
<br />
<br />
The difference between <em>value </em>and <em>value_in_use </em>is that <em>value_in_use</em> is what is currently used and <em>value </em>will be used next time the server is restarted. If you want to have the change take effect immediately then use RECONFIGURE<br />
<br />
As you can see <span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif; font-size: 16px;">xp_cmdshell is turned on</span><br />
<div>
<span style="color: #333333; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif; font-size: 16px;"><br /></span></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here is an example that will turn off xp_cmdshell<br />
<br />
<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">EXECUTE</span> sp_configure <span style="background-color: #fff0f0;">'show advanced options'</span>, <span style="color: #0000dd; font-weight: bold;">1</span>
RECONFIGURE
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">EXECUTE</span> sp_configure <span style="background-color: #fff0f0;">'xp_cmdshell'</span>, <span style="background-color: #fff0f0;">'0'</span>
RECONFIGURE
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">EXECUTE</span> sp_configure <span style="background-color: #fff0f0;">'show advanced options'</span>, <span style="color: #0000dd; font-weight: bold;">0</span>
RECONFIGURE
<span style="color: #008800; font-weight: bold;">GO</span></pre>
</pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"></pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"></pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
To enable a feature use the value 1, to disable a feature use the value 0<br />
<br />
If you prefer the GUI, you can also use that, right click on the database server name in SSMS, select Facets, from the Facet drop down select Surface Area Configuration. You will see the following Surface Area Configuration properties<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQzVpty2tKaLD4dZ0xgXnQk307kqi1PFgOf92zbU-U6LRl-mgd0R-t44w1R4x-0sxf6l9X3j0DbTE19avbp9y9hVZrv3XYd9PTZDKjpgS57laMw15ApTQsUwDcEKKq_nPrl25W/s1600/Facets.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="531" data-original-width="665" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQzVpty2tKaLD4dZ0xgXnQk307kqi1PFgOf92zbU-U6LRl-mgd0R-t44w1R4x-0sxf6l9X3j0DbTE19avbp9y9hVZrv3XYd9PTZDKjpgS57laMw15ApTQsUwDcEKKq_nPrl25W/s640/Facets.png" width="640" /></a></div>
<div class="image_block" style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here you can enable or disable the features you are interested in. You can also export these properties as a policy to use on other servers so that the features are the same on all your servers<br />
<br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Installing everything by default</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here I have mixed feelings myself about what to do. On one hand I don't like to install SSAS or SSRS if there is no need for it, on the other hand I don't feel like adding that stuff 6 months down the road if there is suddenly a need for it. If I do install it, I make sure it at least doesn't run by default but it is disabled.<br />
<br />
There is no benefit in having SSAS, SSRS or SSIS running and using CPU cycles as well as RAM if nobody is using these services. If you do install it and nobody uses it, disable the services, you will have more RAM and CPU cycles for the SQL Server service available.<br />
<br />
<br />
One more thing I want to mention is that I have run into something like this many times.... The Dev or Test server has everything enabled. We deploy to production and oops... CLR is not enabled (quick fix) or SSRS/SSAS is not installed (need to install it, will take longer)<br />
<br />
So make sure before deploying that you check what is enabled and installed on the production box<br />
<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-23258312236269785972019-02-18T13:48:00.000-08:002019-02-19T10:42:05.689-08:00Calculating Sexy Primes, Prime Triplets and Sexy Prime Triplets in SQL Server<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
The other day I was reading something on Hackernews and someone posted a link to a Sexy Primes wikipedia article. I looked at that and then decided to do this in SQL Server because.. why not?<br />
<br />
From that wikipedia link: <a href="https://en.wikipedia.org/wiki/Sexy_prime">https://en.wikipedia.org/wiki/Sexy_prime</a><br />
<br />
<br />
In mathematics, sexy primes are prime numbers that differ from each other by six. For example, the numbers 5 and 11 are both sexy primes, because 11 minus 5 is 6.<br />
<br />
The term "sexy prime" is a pun stemming from the Latin word for six: sex.<br />
<br />
If p + 2 or p + 4 (where p is the lower prime) is also prime, then the sexy prime is part of a prime triplet.<br />
<br />
Ok I did a couple of versions of this over the weekend, I also did a PostgreSQL version: <a href="https://denisgobo.blogspot.com/2019/02/Calculating-Sexy-Primes-Prime-Triplets-and-Sexy-Prime-Triplets-in-PostgreSQL.html">Calculating Sexy Primes, Prime Triplets and Sexy Prime Triplets in PostgreSQL</a><br />
<br />
So first we need a table that will just have the prime numbers<br />
<br />
I decided to populate a table with numbers from 2 till 500 and then use the sieve of Eratosthenes method to delete the non primes<br />
<br />
This will look like this<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #PrimeNumbers(n <span style="color: #007020;">int</span>)
<span style="color: #008800; font-weight: bold;">INSERT</span> <span style="color: #008800; font-weight: bold;">INTO</span> #PrimeNumbers
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #007020;">number</span>
<span style="color: #008800; font-weight: bold;">FROM</span> master..spt_values
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">between</span> <span style="color: #0000dd; font-weight: bold;">2</span> <span style="color: #008800; font-weight: bold;">and</span> <span style="color: #0000dd; font-weight: bold;">500</span>
<span style="color: #888888;">--Sieve method</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @i <span style="color: #007020;">INT</span>
<span style="color: #008800; font-weight: bold;">SET</span> @I = <span style="color: #0000dd; font-weight: bold;">2</span>
WHILE @I <= SQRT(<span style="color: #0000dd; font-weight: bold;">500</span>)
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> <span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers <span style="color: #008800; font-weight: bold;">WHERE</span> N % @I = <span style="color: #0000dd; font-weight: bold;">0</span> <span style="color: #008800; font-weight: bold;">AND</span> N > @I
<span style="color: #008800; font-weight: bold;">SET</span> @I = @I + <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers</pre>
<br />
Thinking about it a little more I decided to do it with a CTE instead of a loop with delete statements, if your tables will be big then the delete method is probably better... it's for you to test that out :-)<br />
<br />
What we are doing is a NOT EXISTS query against the same cte and we are filtering out numbers that are greater than the number in the current row and are not divisible by the current number<br />
<br />
<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">IF OBJECT_ID(<span style="background-color: #fff0f0;">'tempdb..#PrimeNumbers'</span>) <span style="color: #008800; font-weight: bold;">IS</span> <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>
<span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #PrimeNumbers
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #PrimeNumbers(n <span style="color: #007020;">int</span>)
;<span style="color: #008800; font-weight: bold;">WITH</span> cte <span style="color: #008800; font-weight: bold;">AS</span> (
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #007020;">number</span> n
<span style="color: #008800; font-weight: bold;">FROM</span> master..spt_values
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">between</span> <span style="color: #0000dd; font-weight: bold;">2</span> <span style="color: #008800; font-weight: bold;">and</span> <span style="color: #0000dd; font-weight: bold;">500</span>
), PrimeNumbers <span style="color: #008800; font-weight: bold;">as</span> (
<span style="color: #008800; font-weight: bold;">SELECT</span> n
<span style="color: #008800; font-weight: bold;">FROM</span> cte
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">EXISTS</span> (
<span style="color: #008800; font-weight: bold;">SELECT</span> n <span style="color: #008800; font-weight: bold;">FROM</span> cte <span style="color: #008800; font-weight: bold;">as</span> cte2
<span style="color: #008800; font-weight: bold;">WHERE</span> cte.n > cte2.n <span style="color: #008800; font-weight: bold;">AND</span> cte.n % cte2.n = <span style="color: #0000dd; font-weight: bold;">0</span>)
)
<span style="color: #008800; font-weight: bold;">INSERT</span> #PrimeNumbers
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> PrimeNumbers
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers</pre>
<br />
If we run that last select statement, we should have 95 rows<br />
<br />
2<br />
3<br />
5<br />
7<br />
.....<br />
.....<br />
463<br />
467<br />
479<br />
487<br />
491<br />
499<br />
<br />
Now that we have our table filled with prime numbers till 500, it's time to run the queries<br />
<br />
<b>Sexy prime pairs</b><br />
The sexy primes (sequences OEIS: <a href="https://oeis.org/A023201">A023201</a> and OEIS: <a href="https://oeis.org/A046117">A046117</a> in OEIS) below 500 are:<br />
<br />
(5,11), (7,13), (11,17), (13,19), (17,23), (23,29), (31,37), (37,43), (41,47), (47,53), (53,59), (61,67), (67,73), (73,79), (83,89), (97,103), (101,107), (103,109), (107,113), (131,137), (151,157), (157,163), (167,173), (173,179), (191,197), (193,199), (223,229), (227,233), (233,239), (251,257), (257,263), (263,269), (271,277), (277,283), (307,313), (311,317), (331,337), (347,353), (353,359), (367,373), (373,379), (383,389), (433,439), (443,449), (457,463), (461,467).<br />
<br />
<br />
Here is that query for the sexy prime pairs<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #888888;">-- 46 rows.. sexy primes</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> t1.N,t2.N
<span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers t1
<span style="color: #008800; font-weight: bold;">join</span> #PrimeNumbers t2 <span style="color: #008800; font-weight: bold;">on</span> t2.N - t1.N = <span style="color: #0000dd; font-weight: bold;">6</span>
<span style="color: #008800; font-weight: bold;">order</span> <span style="color: #008800; font-weight: bold;">by</span> <span style="color: #0000dd; font-weight: bold;">1</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
It's very simple.. a self join that returns rows where the number from one table alias and the number from the other table alias differ by 6<br />
<br />
<br />
<br />
<br />
<b>Prime triplets</b><br />
The first prime triplets below 500 (sequence <a href="https://oeis.org/A098420">A098420 </a>in the OEIS) are<br />
<br />
(5, 7, 11), (7, 11, 13), (11, 13, 17), (13, 17, 19), (17, 19, 23), (37, 41, 43), (41, 43, 47), (67, 71, 73), (97, 101, 103), (101, 103, 107), (103, 107, 109), (107, 109, 113), (191, 193, 197), (193, 197, 199), (223, 227, 229), (227, 229, 233), (277, 281, 283), (307, 311, 313), (311, 313, 317), (347, 349, 353), (457, 461, 463), (461, 463, 467)<br />
<br />
A prime triplet contains a pair of twin primes (p and p + 2, or p + 4 and p + 6), a pair of cousin primes (p and p + 4, or p + 2 and p + 6), and a pair of sexy primes (p and p + 6).<br />
<br />
So we need to check that the 1st and 3rd number have a difference of 6, we also check that that difference between number 1 and 2 is 2 or 4. That query looks like this<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #888888;">-- 22 rows.. Prime Triplets</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> t1.N <span style="color: #008800; font-weight: bold;">AS</span> N1,t2.N <span style="color: #008800; font-weight: bold;">AS</span> N2, t3.N <span style="color: #008800; font-weight: bold;">AS</span> N3
<span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers t1
<span style="color: #008800; font-weight: bold;">join</span> #PrimeNumbers t2 <span style="color: #008800; font-weight: bold;">on</span> t2.N > t1.N
<span style="color: #008800; font-weight: bold;">join</span> #PrimeNumbers t3 <span style="color: #008800; font-weight: bold;">on</span> t3.N - t1.N = <span style="color: #0000dd; font-weight: bold;">6</span>
<span style="color: #008800; font-weight: bold;">and</span> t3.N > t2.N
<span style="color: #008800; font-weight: bold;">and</span> t2.n - t1.n <span style="color: #008800; font-weight: bold;">IN</span> (<span style="color: #0000dd; font-weight: bold;">2</span>,<span style="color: #0000dd; font-weight: bold;">4</span>)
<span style="color: #008800; font-weight: bold;">order</span> <span style="color: #008800; font-weight: bold;">by</span> <span style="color: #0000dd; font-weight: bold;">1</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<br />
<br />
<br />
<b>Sexy prime triplets</b><br />
Triplets of primes (p, p + 6, p + 12) such that p + 18 is composite are called sexy prime. p p, p+6 and p+12 are all prime, but p+18 is not<br />
<br />
Those below 500 (sequence OEIS: A046118) are:<br />
<br />
(7,13,19), (17,23,29), (31,37,43), (47,53,59), (67,73,79), (97,103,109), (101,107,113), (151,157,163), (167,173,179), (227,233,239), (257,263,269), (271,277,283), (347,353,359), (367,373,379)<br />
<br />
<br />
The query looks like this.. instead of a self join, we do a triple self join, we also check that p + 18 is not a prime number in the line before the order by<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #888888;">-- 14 rows.. Sexy prime triplets</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> t1.N <span style="color: #008800; font-weight: bold;">AS</span> N1,t2.N <span style="color: #008800; font-weight: bold;">AS</span> N2, t3.N <span style="color: #008800; font-weight: bold;">AS</span> N3
<span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers t1
<span style="color: #008800; font-weight: bold;">join</span> #PrimeNumbers t2 <span style="color: #008800; font-weight: bold;">on</span> t2.n - t1.n = <span style="color: #0000dd; font-weight: bold;">6</span>
<span style="color: #008800; font-weight: bold;">join</span> #PrimeNumbers t3 <span style="color: #008800; font-weight: bold;">on</span> t3.N - t1.N = <span style="color: #0000dd; font-weight: bold;">12</span>
<span style="color: #008800; font-weight: bold;">and</span> t3.N > t2.N
<span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">EXISTS</span>( <span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">null</span> <span style="color: #008800; font-weight: bold;">FROM</span> #PrimeNumbers p <span style="color: #008800; font-weight: bold;">WHERE</span> p.n = t1.n +<span style="color: #0000dd; font-weight: bold;">18</span>)
<span style="color: #008800; font-weight: bold;">order</span> <span style="color: #008800; font-weight: bold;">by</span> <span style="color: #0000dd; font-weight: bold;">1</span></pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT6FNKX77nZ2Mdyb4_2voarjgE3Bx9lOS6A7xQsBiwNPU8j67UxIRGKSGHEHFvu7opabR769C7b7oO-2RAouv6POTZiJGEFW7hjwRiTkWqzIEr5ivEXzH554a-sk5omIA6KrHd/s1600/SexyPrimesTriplets.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="893" data-original-width="1166" height="490" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT6FNKX77nZ2Mdyb4_2voarjgE3Bx9lOS6A7xQsBiwNPU8j67UxIRGKSGHEHFvu7opabR769C7b7oO-2RAouv6POTZiJGEFW7hjwRiTkWqzIEr5ivEXzH554a-sk5omIA6KrHd/s640/SexyPrimesTriplets.PNG" width="640" /></a></div>
<br />
<br />
And that's it for this post.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-16771259.post-53606311310924489132019-02-14T06:53:00.000-08:002019-02-14T10:23:43.917-08:00Finding rows where the column starts or ends with a 'bad' characterA coworker came to me asking me for some help. He had some issues trying to convert some data from a staging table to numeric. I asked him to show me the data in SSMS and at first glance it looked good to me. Then I asked where the data came from, he said it came from Excel.<br />
<br />
Aha... I have plenty of war stories with Excel so I said, it's probably some non printable character that is in the column.. either a tab (char(9)) or a non breaking space (char(160))..especially if the value was copied from the internet<br />
<br />
He said isnumeric was returning 0 for rows that looked valid, I then told him to run this query on those rows<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> ASCII(<span style="color: #008800; font-weight: bold;">LEFT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)),
ASCII(<span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)),*
<span style="color: #008800; font-weight: bold;">FROM</span> StagingData s</pre>
<br />
That would give them the ascii numerical value. For example a tab is 9, linefeed = 10....<br />
<br />
Here is a chart for the characters between 0 and 32<br />
<table class="wikitable" style="background-color: #f8f9fa; border-collapse: collapse; border: 1px solid rgb(162, 169, 177); color: #222222; font-family: sans-serif; font-size: 14px; margin: 1em 0px; text-align: center;"><tbody>
<tr><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Binary_numeral_system" style="background: none; color: #0b0080; text-decoration-line: none;" title="Binary numeral system">Binary</a></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><a href="https://en.wikipedia.org/wiki/Octal" style="background: none; color: #0b0080; text-decoration-line: none;" title="Octal">Oct</a></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><a href="https://en.wikipedia.org/wiki/Decimal" style="background: none; color: #0b0080; text-decoration-line: none;" title="Decimal">Dec</a></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><a href="https://en.wikipedia.org/wiki/Hexadecimal" style="background: none; color: #0b0080; text-decoration-line: none;" title="Hexadecimal">Hex</a></th><th colspan="3" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;">Abbreviation</th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><sup class="reference" id="cite_ref-42" style="font-size: 11.2px; font-weight: normal; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-42" style="background: none; color: #0b0080; text-decoration-line: none;">[b]</a></sup></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><sup class="reference" id="cite_ref-43" style="font-size: 11.2px; font-weight: normal; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-43" style="background: none; color: #0b0080; text-decoration-line: none;">[c]</a></sup></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;"><sup class="reference" id="cite_ref-44" style="font-size: 11.2px; font-weight: normal; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-44" style="background: none; color: #0b0080; text-decoration-line: none;">[d]</a></sup></th><th rowspan="2" style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;">Name (1967)</th></tr>
<tr><th style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;">1963</th><th style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;">1965</th><th style="background-color: #eaecf0; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: center;">1967</th></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0000</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">00</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">NULL</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">NUL</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␀</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5E@" style="background: none; color: #0b0080; text-decoration-line: none;" title="^@">^@</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5C0" style="background: none; color: #0b0080; text-decoration-line: none;" title="\0">\0</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Null_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Null character">Null</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0001</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">01</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SOM</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SOH</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␁</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EA" style="background: none; color: #0b0080; text-decoration-line: none;" title="^A">^A</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Start_of_Heading" style="background: none; color: #0b0080; text-decoration-line: none;" title="Start of Heading">Start of Heading</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0010</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">002</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">2</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">02</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">EOA</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">STX</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␂</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EB" style="background: none; color: #0b0080; text-decoration-line: none;" title="^B">^B</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Start_of_Text" style="background: none; color: #0b0080; text-decoration-line: none;" title="Start of Text">Start of Text</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0011</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">003</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">3</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">03</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">EOM</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ETX</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␃</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EC" style="background: none; color: #0b0080; text-decoration-line: none;" title="^C">^C</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/End-of-Text_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="End-of-Text character">End of Text</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0100</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">004</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">4</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">04</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">EOT</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␄</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5ED" style="background: none; color: #0b0080; text-decoration-line: none;" title="^D">^D</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/End-of-Transmission_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="End-of-Transmission character">End of Transmission</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0101</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">005</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">5</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">05</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">WRU</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ENQ</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␅</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EE" style="background: none; color: #0b0080; text-decoration-line: none;" title="^E">^E</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Enquiry_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Enquiry character">Enquiry</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0110</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">006</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">6</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">06</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">RU</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ACK</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␆</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EF" style="background: none; color: #0b0080; text-decoration-line: none;" title="^F">^F</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Acknowledge_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Acknowledge character">Acknowledgement</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 0111</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">007</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">7</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">07</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">BELL</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">BEL</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␇</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EG" style="background: none; color: #0b0080; text-decoration-line: none;" title="^G">^G</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Ca" style="background: none; color: #0b0080; text-decoration-line: none;" title="\a">\a</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Bell_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Bell character">Bell</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1000</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">010</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">8</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">08</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">FE0</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">BS</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␈</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EH" style="background: none; color: #0b0080; text-decoration-line: none;" title="^H">^H</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a href="https://en.wikipedia.org/wiki/Backspace" style="background: none; color: #0b0080; text-decoration-line: none;" title="Backspace">\b</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Backspace" style="background: none; color: #0b0080; text-decoration-line: none;" title="Backspace">Backspace</a><sup class="reference" id="cite_ref-45" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-45" style="background: none; color: #0b0080; text-decoration-line: none;">[e]</a></sup><sup class="reference" id="cite_ref-bsp_del_mismatch_46-0" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-bsp_del_mismatch-46" style="background: none; color: #0b0080; text-decoration-line: none;">[f]</a></sup></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1001</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">011</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">9</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">09</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">HT/SK</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">HT</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␉</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EI" style="background: none; color: #0b0080; text-decoration-line: none;" title="^I">^I</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Ct" style="background: none; color: #0b0080; text-decoration-line: none;" title="\t">\t</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Horizontal_Tab" style="background: none; color: #0b0080; text-decoration-line: none;" title="Horizontal Tab">Horizontal Tab</a><sup class="reference" id="cite_ref-47" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-47" style="background: none; color: #0b0080; text-decoration-line: none;">[g]</a></sup></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1010</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">012</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">10</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0A</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">LF</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␊</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EJ" style="background: none; color: #0b0080; text-decoration-line: none;" title="^J">^J</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Cn" style="background: none; color: #0b0080; text-decoration-line: none;" title="\n">\n</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Line_Feed" style="background: none; color: #0b0080; text-decoration-line: none;" title="Line Feed">Line Feed</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1011</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">013</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">11</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0B</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">VTAB</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">VT</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␋</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EK" style="background: none; color: #0b0080; text-decoration-line: none;" title="^K">^K</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Cv" style="background: none; color: #0b0080; text-decoration-line: none;" title="\v">\v</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Vertical_Tab" style="background: none; color: #0b0080; text-decoration-line: none;" title="Vertical Tab">Vertical Tab</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1100</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">014</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">12</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0C</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">FF</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␌</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EL" style="background: none; color: #0b0080; text-decoration-line: none;" title="^L">^L</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Cf" style="background: none; color: #0b0080; text-decoration-line: none;" title="\f">\f</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Form_Feed" style="background: none; color: #0b0080; text-decoration-line: none;" title="Form Feed">Form Feed</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1101</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">015</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">13</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0D</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">CR</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␍</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EM" style="background: none; color: #0b0080; text-decoration-line: none;" title="^M">^M</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Cr" style="background: none; color: #0b0080; text-decoration-line: none;" title="\r">\r</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Carriage_Return" style="background: none; color: #0b0080; text-decoration-line: none;" title="Carriage Return">Carriage Return</a><sup class="reference" id="cite_ref-48" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-48" style="background: none; color: #0b0080; text-decoration-line: none;">[h]</a></sup></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1110</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">016</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">14</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0E</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SO</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␎</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EN" style="background: none; color: #0b0080; text-decoration-line: none;" title="^N">^N</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Shift_Out" style="background: none; color: #0b0080; text-decoration-line: none;" title="Shift Out">Shift Out</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">000 1111</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">017</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">15</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">0F</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SI</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␏</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EO" style="background: none; color: #0b0080; text-decoration-line: none;" title="^O">^O</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Shift_In" style="background: none; color: #0b0080; text-decoration-line: none;" title="Shift In">Shift In</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0000</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">020</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">16</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">10</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DC0</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DLE</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␐</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EP" style="background: none; color: #0b0080; text-decoration-line: none;" title="^P">^P</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Data_Link_Escape" style="background: none; color: #0b0080; text-decoration-line: none;" title="Data Link Escape">Data Link Escape</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0001</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">021</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">17</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">11</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DC1</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␑</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EQ" style="background: none; color: #0b0080; text-decoration-line: none;" title="^Q">^Q</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Device_Control_1" style="background: none; color: #0b0080; text-decoration-line: none;" title="Device Control 1">Device Control 1</a> (often <a class="mw-redirect" href="https://en.wikipedia.org/wiki/XON" style="background: none; color: #0b0080; text-decoration-line: none;" title="XON">XON</a>)</td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0010</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">022</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">18</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">12</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DC2</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␒</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5ER" style="background: none; color: #0b0080; text-decoration-line: none;" title="^R">^R</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Device_Control_2" style="background: none; color: #0b0080; text-decoration-line: none;" title="Device Control 2">Device Control 2</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0011</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">023</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">19</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">13</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DC3</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␓</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5ES" style="background: none; color: #0b0080; text-decoration-line: none;" title="^S">^S</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Device_Control_3" style="background: none; color: #0b0080; text-decoration-line: none;" title="Device Control 3">Device Control 3</a> (often <a class="mw-redirect" href="https://en.wikipedia.org/wiki/XOFF" style="background: none; color: #0b0080; text-decoration-line: none;" title="XOFF">XOFF</a>)</td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0100</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">024</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">20</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">14</td><td colspan="3" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">DC4</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␔</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5ET" style="background: none; color: #0b0080; text-decoration-line: none;" title="^T">^T</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Device_Control_4" style="background: none; color: #0b0080; text-decoration-line: none;" title="Device Control 4">Device Control 4</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0101</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">025</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">21</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">15</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ERR</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">NAK</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␕</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EU" style="background: none; color: #0b0080; text-decoration-line: none;" title="^U">^U</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Negative-acknowledge_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Negative-acknowledge character">Negative Acknowledgement</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0110</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">026</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">22</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">16</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SYNC</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SYN</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␖</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EV" style="background: none; color: #0b0080; text-decoration-line: none;" title="^V">^V</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Synchronous_Idle" style="background: none; color: #0b0080; text-decoration-line: none;" title="Synchronous Idle">Synchronous Idle</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 0111</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">027</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">23</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">17</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">LEM</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ETB</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␗</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EW" style="background: none; color: #0b0080; text-decoration-line: none;" title="^W">^W</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/End-of-Transmission-Block_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="End-of-Transmission-Block character">End of Transmission Block</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1000</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">030</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">24</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">18</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S0</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">CAN</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␘</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EX" style="background: none; color: #0b0080; text-decoration-line: none;" title="^X">^X</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Cancel_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Cancel character">Cancel</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1001</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">031</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">25</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">19</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S1</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">EM</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␙</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EY" style="background: none; color: #0b0080; text-decoration-line: none;" title="^Y">^Y</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/End_of_Medium" style="background: none; color: #0b0080; text-decoration-line: none;" title="End of Medium">End of Medium</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1010</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">032</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">26</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1A</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S2</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SS</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">SUB</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␚</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5EZ" style="background: none; color: #0b0080; text-decoration-line: none;" title="^Z">^Z</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Substitute_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Substitute character">Substitute</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1011</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">033</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">27</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1B</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S3</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">ESC</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␛</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;">^[</code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5Ce" style="background: none; color: #0b0080; text-decoration-line: none;" title="\e">\e</a></code><sup class="reference" id="cite_ref-49" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-49" style="background: none; color: #0b0080; text-decoration-line: none;">[i]</a></sup></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a href="https://en.wikipedia.org/wiki/Escape_character" style="background: none; color: #0b0080; text-decoration-line: none;" title="Escape character">Escape</a><sup class="reference" id="cite_ref-50" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-50" style="background: none; color: #0b0080; text-decoration-line: none;">[j]</a></sup></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1100</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">034</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">28</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1C</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S4</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">FS</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␜</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/%5E%5C" style="background: none; color: #0b0080; text-decoration-line: none;" title="^\">^\</a></code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/File_Separator" style="background: none; color: #0b0080; text-decoration-line: none;" title="File Separator">File Separator</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1101</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">035</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">29</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1D</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S5</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">GS</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␝</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;">^]</code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Group_Separator" style="background: none; color: #0b0080; text-decoration-line: none;" title="Group Separator">Group Separator</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1110</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">036</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">30</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1E</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S6</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">RS</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␞</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;">^^</code><sup class="reference" id="cite_ref-51" style="font-size: 11.2px; line-height: 1; unicode-bidi: isolate; white-space: nowrap;"><a href="https://en.wikipedia.org/wiki/ASCII#cite_note-51" style="background: none; color: #0b0080; text-decoration-line: none;">[k]</a></sup></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Record_Separator" style="background: none; color: #0b0080; text-decoration-line: none;" title="Record Separator">Record Separator</a></td></tr>
<tr><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">001 1111</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">037</td><td style="background: rgb(204, 255, 255); border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">31</td><td style="background: lightblue; border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">1F</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">S7</td><td colspan="2" style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;">US</td><td style="border: 1px solid rgb(162, 169, 177); font-size: large; padding: 0.2em 0.4em;">␟</td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"><code style="border-radius: 2px; border: 1px solid rgb(234, 236, 240); color: black; font-family: monospace, monospace; padding: 1px 4px;">^_</code></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em;"></td><td style="border: 1px solid rgb(162, 169, 177); padding: 0.2em 0.4em; text-align: left;"><a class="mw-redirect" href="https://en.wikipedia.org/wiki/Unit_Separator" style="background: none; color: #0b0080; text-decoration-line: none;" title="Unit Separator">Unit Separator</a></td></tr>
</tbody></table>
<br>
Source: <a href="https://en.wikipedia.org/wiki/ASCII">https://en.wikipedia.org/wiki/ASCII</a><br />
<br />
<br />
<br />
He then ran the following to grab all the rows that ended or started with tabs<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">LEFT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>) = <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">9</span>)
<span style="color: #008800; font-weight: bold;">OR</span> <span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>) = <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">9</span>)</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<br />
<br />
<br />
<br />
So let's take another look at this to see how we can make this a little better<br />
<br />
Let's create a table that will hold these bad characters that we don't want, in my case ACII values 1 untill 32<br />
<br />
Here is what we will do to create and populate the table<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> BadCharacters(
BadChar <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
ASCIINumber <span style="color: #007020;">int</span> <span style="color: #008800; font-weight: bold;">NOT</span> <span style="color: #008800; font-weight: bold;">NULL</span>,
<span style="color: #008800; font-weight: bold;">CONSTRAINT</span> pk_BadCharacters
<span style="color: #008800; font-weight: bold;">PRIMARY</span> <span style="color: #008800; font-weight: bold;">KEY</span> CLUSTERED( BadChar )
)
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">INSERT</span> BadCharacters
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #007020;">char</span>(<span style="color: #007020;">number</span>),<span style="color: #007020;">number</span>
<span style="color: #008800; font-weight: bold;">FROM</span> master..SPT_VALUES
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">BETWEEN</span> <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #0000dd; font-weight: bold;">32</span>
<span style="color: #008800; font-weight: bold;">OR</span> <span style="color: #007020;">number</span> = <span style="color: #0000dd; font-weight: bold;">160</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
A quick look at the data looks like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> BadCharacters</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjIfnD0JU_sHHma-s1uigHNb2ZOS43VjWdiZ3Y2Nukxd7rrkz1M_WEiMaJDrtRcUuuoGJAtLM7iLbAVZLwu_5CjFk0F6QqrStgByY4GbwtjZH8bz3FmF9BNIuCJZ_Nr9mXecq8/s1600/badCharCharacters.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="376" data-original-width="194" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjIfnD0JU_sHHma-s1uigHNb2ZOS43VjWdiZ3Y2Nukxd7rrkz1M_WEiMaJDrtRcUuuoGJAtLM7iLbAVZLwu_5CjFk0F6QqrStgByY4GbwtjZH8bz3FmF9BNIuCJZ_Nr9mXecq8/s640/badCharCharacters.PNG" width="330" /></a></div>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<br />
Now let's create our staging table and insert some data so that we can do some tests<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> StagingData (SomeColumn <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">255</span>) )
<span style="color: #008800; font-weight: bold;">INSERT</span> StagingData
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),s1.<span style="color: #007020;">number</span>) + <span style="background-color: #fff0f0;">'.'</span> + <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),s2.<span style="color: #007020;">number</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> master..SPT_VALUES s1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> master..SPT_VALUES s2
<span style="color: #008800; font-weight: bold;">WHERE</span> s1.<span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> s2.<span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="background-color: #fff0f0;">
</span></pre>
<br />
That inserted 4194304 rows on my machine<br />
<br />
Time to insert some of that bad data<br />
<br />
Here is what some of the data inserted will look like<br />
<br />
2.1 <br />
2.2 <br />
2.3 <br />
2.4 <br />
2.5 <br />
2.6 <br />
2.7 <br />
2.8 <br />
<br />
And this is the query to generated and insert those bad rows, on my machine it generated 1089 such rows<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">;<span style="color: #008800; font-weight: bold;">WITH</span> cte <span style="color: #008800; font-weight: bold;">as</span>(<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),<span style="color: #007020;">number</span>) <span style="color: #008800; font-weight: bold;">as</span> num
<span style="color: #008800; font-weight: bold;">FROM</span> master..SPT_VALUES
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'P'</span>
<span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #007020;">number</span> <span style="color: #008800; font-weight: bold;">BETWEEN</span> <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #008800; font-weight: bold;">AND</span> <span style="color: #0000dd; font-weight: bold;">1000</span>)
<span style="color: #888888;">--INSERT StagingData</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> b.BadChar + c1.num + <span style="background-color: #fff0f0;">'.'</span> + c2.num + b2.BadChar
<span style="color: #008800; font-weight: bold;">FROM</span> cte c1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> cte c2
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> c1.num = b.ASCIINumber
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b2 <span style="color: #008800; font-weight: bold;">on</span> c2.num = b2.ASCIINumber</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
The query create a value by using a bad value, a number a dot a number and a bad value, you can see those values above<br />
<br />
<br />
Now it's time to find these bad rows, but before we do that, let's add an index<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">INDEX</span> ix_StagingData <span style="color: #008800; font-weight: bold;">on</span> StagingData(SomeColumn)</pre>
<br />
<br />
OK, we are ready...<br />
<br />
Of course I here you saying, why don't we just do this<br />
<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData
<span style="color: #008800; font-weight: bold;">WHERE</span> TRY_CONVERT(<span style="color: #007020;">numeric</span>(<span style="color: #0000dd; font-weight: bold;">20</span>,<span style="color: #0000dd; font-weight: bold;">10</span>),SomeColumn) <span style="color: #008800; font-weight: bold;">IS</span> <span style="color: #008800; font-weight: bold;">NULL</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<div>
<br /></div>
Well, yes that gives me everything that can't be converted to numeric, but I want to see what those characters are<br />
<div>
<br /></div>
<div>
<br />
Before we start, let's set statistics io on so that we can look at some performance<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SET</span> <span style="color: #008800; font-weight: bold;">STATISTICS</span> IO <span style="color: #008800; font-weight: bold;">ON</span>
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">
</span></pre>
<br />
Here are the queries to find the bad characters at the start<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> b.BadChar = <span style="color: #008800; font-weight: bold;">LEFT</span>(s.SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> s.SomeColumn <span style="color: #008800; font-weight: bold;">like</span> b.BadChar +<span style="background-color: #fff0f0;">'%'</span></pre>
<br />
<br />
Here is what the reads look like<br />
<br />
<i>(1089 row(s) affected)</i><br />
<i>Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'StagingData'. Scan count 9, logical reads <span style="color: red;"><b>10851</b></span>, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i><br /></i>
<i>(1089 row(s) affected)</i><br />
<i>Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'StagingData'. Scan count 33, logical reads <span style="color: red;"><b>135</b></span>, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<br />
As you can see from the stats, the top query is non-SARGable and generates a lot more reads, the bottom query can use the index. Always make sure to write your queries in a way so that SQL Server can you an index<br />
<br />
<br />
<br />
What about the last character, how can we find those<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> b.BadChar = <span style="color: #008800; font-weight: bold;">RIGHT</span>(s.SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> s.SomeColumn <span style="color: #008800; font-weight: bold;">like</span> +<span style="background-color: #fff0f0;">'%'</span> + b.BadChar </pre>
<br />
<br />
Here are the stats again<br />
<br />
(1089 row(s) affected)<br />
Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
Table 'StagingData'. Scan count 9, logical reads <span style="color: red;"><b>10851</b></span>, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
<br />
(1089 row(s) affected)<br />
Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
Table 'StagingData'. Scan count 33, logical reads <span style="color: red;"><b>445863</b></span>, physical reads 0, read-ahead reads 13, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.<br />
<br />
<br />
So both of these queries suck the life out of your SQL Server instance, so what can be done?<br />
<br />
One thing we can do is add a computed column to the table that will hold just the last character of the column, then we can index the computed column<br />
<br />
Here are the commands to do that<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">ALTER</span> <span style="color: #008800; font-weight: bold;">TABLE</span> StagingData <span style="color: #008800; font-weight: bold;">ADD</span> RightChar <span style="color: #008800; font-weight: bold;">as</span> <span style="color: #008800; font-weight: bold;">RIGHT</span>(SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">INDEX</span> ix_RightChar <span style="color: #008800; font-weight: bold;">on</span> StagingData(RightChar)
<span style="color: #008800; font-weight: bold;">GO</span></pre>
<br />
And now we can just run the same queries again<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> b.BadChar = <span style="color: #008800; font-weight: bold;">RIGHT</span>(s.SomeColumn,<span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> StagingData s
<span style="color: #008800; font-weight: bold;">JOIN</span> BadCharacters b <span style="color: #008800; font-weight: bold;">on</span> s.SomeColumn <span style="color: #008800; font-weight: bold;">like</span> +<span style="background-color: #fff0f0;">'%'</span> + b.BadChar </pre>
<br />
<br />
Here are the stats<br />
<br />
<i>(1089 row(s) affected)</i><br />
<i>Table 'StagingData'. Scan count 33, logical reads <span style="color: red;"><b>1223</b></span>, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i><br /></i>
<i>(1089 row(s) affected)</i><br />
<i>Table 'StagingData'. Scan count 33, logical reads <span style="color: red;"><b>1223</b></span>, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<i>Table 'BadCharacters'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</i><br />
<br />
<br />
Did you expect to get the same exact reads for both queries?<br />
<br />
So what is going on? Well lets take a look<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvq0gmVWZRpl6CcwCou7Sh8csyZpbXBSxd1u7ckyS2PbqchNmUOZAS1jCkBEikvOY-mnmPwoR-MmVXcqTGAbc3uwv0C36Z2tFGIwerzG5u_q4ps8ruqBE3WqESn5OXAPmyLIp6/s1600/BadCharFinal+Plan.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="489" data-original-width="1016" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvq0gmVWZRpl6CcwCou7Sh8csyZpbXBSxd1u7ckyS2PbqchNmUOZAS1jCkBEikvOY-mnmPwoR-MmVXcqTGAbc3uwv0C36Z2tFGIwerzG5u_q4ps8ruqBE3WqESn5OXAPmyLIp6/s640/BadCharFinal+Plan.PNG" width="640" /></a></div>
<br />
In both cases, the optimizer was smart enough to use the index on the computed column<br />
<br />
Hopefully this will make someone's life easier and you can expand the table to add other character you consider bad. You can also add constraint to reject values or you can add triggers and then move those bad rows to a bad rows table<br />
<br />
Finally if you need to worry about unicode you might want to change the table to be nvarchar<br />
<br />
Enjoy.. importing that data..... we all know..it's only getting bigger and bigger<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-85115751426748098712019-02-12T12:28:00.000-08:002019-02-13T06:59:15.308-08:00Using SonarQube, SonarQube Scanner and the sonar-tsql-plugin to run static code analysisIn the previous post <a href="https://sqlservercode.blogspot.com/2019/02/scripting-out-procs-and-user-defined-functions-powershell.html">Scripting out procs and user defined functions with PowerShell</a>, we scripted out some procs and functions from the Adventureworks database so that we can run some static code analysis. Today we will install SonarQube, SonarQube Scanner and the sonar-tsql-plugin. First thing we need is to grab Java if you don't have it installed. I know I know... I uninstalled it as well.. sigh<br />
<br />
Anyway.. after you have Java installed, you can grab SonarCube here: <a href="https://www.sonarqube.org/downloads/">https://www.sonarqube.org/downloads/</a><br />
<br />
Create a folder named sonarqube-7.6 on the C drive, download SonarCube and extract it in C:\sonarqube-7.6\<br />
<br />
Next we need Sonar Cube Scanner, You can download it here: <a href="https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner">https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner</a><br />
<br />
Create a folder name C:\sonar-scanner-cli-3.3.0.1492-windows and extract the Sonar Cube Scanner file there<br />
<br />
Finally we need the sonar-tsql-plugin, you can download that here <a href="https://github.com/gretard/sonar-tsql-plugin/releases">https://github.com/gretard/sonar-tsql-plugin/releases</a><br />
Grab the file named: sonar-tsqlopen-plugin-0.9.0.jar and download it<br />
Place the jar file in the folder C:\sonarqube-7.6\sonarqube-7.6\extensions\plugins\<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge9srgTBQmE3TY0JlI-fAXDJt9SbDdKrXdqB6VYdsDqv9IJjfl6djVneD5pxAzOu9Gkbg4x7z9cijXRD933DVm8k-9NREn7Bp_RsCesOly_Eg2tcCYNtUfKiBYipScT3Hs0cRN/s1600/EXtensions.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="sonar-tsqlopen-plugin" border="0" data-original-height="184" data-original-width="569" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge9srgTBQmE3TY0JlI-fAXDJt9SbDdKrXdqB6VYdsDqv9IJjfl6djVneD5pxAzOu9Gkbg4x7z9cijXRD933DVm8k-9NREn7Bp_RsCesOly_Eg2tcCYNtUfKiBYipScT3Hs0cRN/s640/EXtensions.PNG" title="sonar-tsqlopen-plugin" width="640" /></a></div>
<br />
<br />
Now it's time to create some environmental variables. In an explorer window, paste this into an address bar<br />
<br />
Control Panel\System and Security\System<br />
Click on Advanced System Settings, click on Environment Variable, click on new<br />
<br />
In the variable name add SONAR_RUNNER_HOME<br />
In the variable value add C:\sonar-scanner-cli-3.3.0.1492-windows<br />
<br />
It will look like this<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCdXzgIJJQ3QDqaKOL3Op7HNLv5kYddGMPBQw6gpsb2YP78s6_41xskeUjIAdNmT6tMWfRWpVOT5NqzCGATcl7rWTdKamVL9McxGsci9z9H5h8oIcmvdrQ-ADTldr8WFl9mFsJ/s1600/Environment+Variables.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="403" data-original-width="741" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCdXzgIJJQ3QDqaKOL3Op7HNLv5kYddGMPBQw6gpsb2YP78s6_41xskeUjIAdNmT6tMWfRWpVOT5NqzCGATcl7rWTdKamVL9McxGsci9z9H5h8oIcmvdrQ-ADTldr8WFl9mFsJ/s640/Environment+Variables.PNG" width="640" /></a></div>
<br />
There is one more thing to do, we need to add something to the path<br />
On older versions of windows... add the line below at the end of the path variable, on newer versions, just click on New and paste the line below<br />
<br />
;%SONAR_RUNNER_HOME%\bin;<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTX3Iq4iP1RtHGIDFYwLRTL9bgnV2ximPEM_Z1HzgWJU8zZSQ91HTtitUiMUP5t7EPN6VdiJjRGspadAi0avEd4uzgkuQa5y49D7VHK6ZJ3-OSyCKFYXqHFgEWYjydLbVchI_/s1600/Path.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="445" data-original-width="634" height="448" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTX3Iq4iP1RtHGIDFYwLRTL9bgnV2ximPEM_Z1HzgWJU8zZSQ91HTtitUiMUP5t7EPN6VdiJjRGspadAi0avEd4uzgkuQa5y49D7VHK6ZJ3-OSyCKFYXqHFgEWYjydLbVchI_/s640/Path.PNG" width="640" /></a></div>
<br />
Ok time to run (and fail) SonarQube finally<br />
<br />
Go to the folder C:\sonarqube-7.6\sonarqube-7.6\bin\windows-x86-32 and kick off the script <b>StartSonar.bat</b><br />
<br />
If you get an error about 32 or 64 bit, then run the script from the windows-x86-64 folder<br />
<br />
If you run the script, if you are lucky, you won't get an error, but if you do is it this one?<br />
<br />
<i><br /></i>
<i>jvm 1 | Error: <b>missing `server' JVM </b>at `C:\Program Files (x86)\Java\jre1.8.0_201\bin\server\jvm.dll'.</i><br />
<i>jvm 1 | Please install or use the JRE or JDK that contains these missing components.</i><br />
<br />
C:\sonarqube-7.6\sonarqube-7.6\bin\windows-x86-32>StartSonar.bat<br />
wrapper | ERROR: Another instance of the SonarQube application is already running.<br />
Press any key to continue . . .<br />
C:\sonarqube-7.6\sonarqube-7.6\bin\windows-x86-32>StartSonar.bat<br />
wrapper | --> Wrapper Started as Console<br />
wrapper | Launching a JVM...<br />
jvm 1 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org<br />
jvm 1 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.<br />
jvm 1 |<br />
jvm 1 | 2019.02.12 13:22:02 INFO app[][o.s.a.AppFileSystem] Cleaning or creating temp directory C:\sonarqube-7.6\sonarqube-7.6\temp<br />
jvm 1 | 2019.02.12 13:22:02 INFO app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001<br />
jvm 1 | 2019.02.12 13:22:02 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [C:\sonarqube-7.6\sonarqube-7.6\elasticsearch]: C:\Program Files (x86)\Java\jre1.8.0_201\bin\java -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+AlwaysPreTouch -server -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -Djdk.io.permissionsUseCanonicalPath=true -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j.skipJansi=true -Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Delasticsearch -Des.path.home=C:\sonarqube-7.6\sonarqube-7.6\elasticsearch -cp lib/* org.elasticsearch.bootstrap.Elasticsearch -Epath.conf=C:\sonarqube-7.6\sonarqube-7.6\temp\conf\es<br />
jvm 1 | 2019.02.12 13:22:02 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running<br />
jvm 1 | Error: missing `server' JVM at `C:\Program Files (x86)\Java\jre1.8.0_201\bin\server\jvm.dll'.<br />
jvm 1 | Please install or use the JRE or JDK that contains these missing components.<br />
<br />
<br />
So to quickly fix this create a server folder in the java bin location from the error message<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkFgKj2Ios09Ktyjp_YNJRZ3SVwETtt4xctO9gRR7WQUyVhLGodpfBJauvZXQAjsRBFUFf0KmWs5ChnXZ7fSXu-5-IZAQBfD912JL3p0Jnlldpev4kp_bGOOaTgerFT0oZwPfH/s1600/Server.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="207" data-original-width="577" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkFgKj2Ios09Ktyjp_YNJRZ3SVwETtt4xctO9gRR7WQUyVhLGodpfBJauvZXQAjsRBFUFf0KmWs5ChnXZ7fSXu-5-IZAQBfD912JL3p0Jnlldpev4kp_bGOOaTgerFT0oZwPfH/s640/Server.PNG" width="640" /></a>
<br />
<br />
Now grab the files from the client folder and copy them to the server folder<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv-wgbnOaXY5LqDAhgOoOfvUTlxoQZZEl4BJC55u-4asWMuR3s0mwL7ZsfoZxu49wRu4lgMj6jc_JhU1tjF32wCgr7yhzUaf5d8r3mlv5O1tXZZtslBeeWCnpM3uOwyG3KnbsQ/s1600/client.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="188" data-original-width="562" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv-wgbnOaXY5LqDAhgOoOfvUTlxoQZZEl4BJC55u-4asWMuR3s0mwL7ZsfoZxu49wRu4lgMj6jc_JhU1tjF32wCgr7yhzUaf5d8r3mlv5O1tXZZtslBeeWCnpM3uOwyG3KnbsQ/s640/client.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Ok, we are ready to run the file again, rerun the command and the last 2 lines should be something like this<br />
<br />
jvm 1 | 2019.02.12 13:25:53 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up<br />
jvm 1 | 2019.02.12 13:25:53 INFO app[][o.s.a.SchedulerImpl] SonarQube is up<br />
<br />
Navigate to http://localhost:9000/ login with admin for username and password<br />
<br />
Now we need to do one more thing and we are ready, open notepad or you favorite text editor, paste the following<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"># Required metadata
sonar.projectKey=StaticCodeAnalysis.project
sonar.projectName=Static Code Analysis project
sonar.projectVersion=<span style="color: #6600ee; font-weight: bold;">1</span>.<span style="color: #6600ee; font-weight: bold;">0</span>
sonar.sources=StoredProcedures,UserDefinedFunctions
sonar.host.url=http://localhost:9000
#sonar.exclusions=**/bin/**/*.*,**/obj/**/*.*,**/*.sqlproj
# Comma-separated paths to directories of source codes to be analyzed.
# Path is relative to the sonar-project.properties file.
# Replace <span style="background-color: #fff0f0;">"\"</span> by <span style="background-color: #fff0f0;">"/"</span> <span style="color: #008800; font-weight: bold;">on</span> Windows.
# Since SonarQube <span style="color: #6600ee; font-weight: bold;">4</span>.<span style="color: #6600ee; font-weight: bold;">2</span>, this property is optional.
# <span style="color: #008800; font-weight: bold;">If</span> not <span style="color: #008800; font-weight: bold;">set</span>, SonarQube starts looking <span style="color: #008800; font-weight: bold;">for</span> source code
# from the directory containing the sonar-project.properties file.
# Language
sonar.language=tsql
#Encoding of the source code
#sonar.sourceEncoding=UTF<span style="color: #6600ee; font-weight: bold;">-8</span></pre>
<br />
Save that as sonar-project.properties in the folder where your code is located, in our case it is in C:\temp<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinFEyHop2LYyZenueYkoGi59i6P7t2cWNwKZ-E2Q-ssfeG9lGDo0XhqySipVHxGbwFz-gX1lR98vPcTefHxCbf6l9eUo9Vi2qkmwWBDgm80JAP3JjGctNjWTxYdK0-fDJhb3tB/s1600/Sonar+properties.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="220" data-original-width="343" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinFEyHop2LYyZenueYkoGi59i6P7t2cWNwKZ-E2Q-ssfeG9lGDo0XhqySipVHxGbwFz-gX1lR98vPcTefHxCbf6l9eUo9Vi2qkmwWBDgm80JAP3JjGctNjWTxYdK0-fDJhb3tB/s400/Sonar+properties.PNG" width="400" /></a></div>
<br />
<br />
<br />
<div>
<br /></div>
Alright.. it's time to run the static code analysis...<br />
<br />
Open a command window, cd to the C;\temp folder, and paste following<br />
<br />
C:\sonar-scanner-cli-3.3.0.1492-windows\sonar-scanner-3.3.0.1492-windows\bin\sonar-scanner.bat<br />
<br />
You should see something like the following<br />
<br />
<i>C:\temp>C:\sonar-scanner-cli-3.3.0.1492-windows\sonar-scanner-3.3.0.1492-windows\bin\sonar-scanner.bat</i><br />
<i>INFO: Scanner configuration file: C:\sonar-scanner-cli-3.3.0.1492-windows\sonar-scanner-3.3.0.1492-windows\bin\..\conf\sonar-scanner.properties</i><br />
<i>INFO: Project root configuration file: C:\temp\sonar-project.properties</i><br />
<i>INFO: SonarQube Scanner 3.3.0.1492</i><br />
<i>INFO: Java 1.8.0_121 Oracle Corporation (64-bit)</i><br />
<i>INFO: Windows 10 10.0 amd64</i><br />
<i>INFO: User cache: C:\Users\denis\.sonar\cache</i><br />
<i>INFO: SonarQube server 7.6.0</i><br />
<i>INFO: Default locale: "en_US", source code encoding: "windows-1252" (analysis is platform dependent)</i><br />
<i>INFO: Load global settings</i><br />
<i>INFO: Load global settings (done) | time=78ms</i><br />
<i>INFO: Server id: BF41A1F2-AWji9AZ8kkLV5J16bA1i</i><br />
<i>INFO: User cache: C:\Users\denis\.sonar\cache</i><br />
<i>INFO: Load/download plugins</i><br />
<i>INFO: Load plugins index</i><br />
<i>INFO: Load plugins index (done) | time=31ms</i><br />
<i>INFO: Load/download plugins (done) | time=47ms</i><br />
<i>INFO: Process project properties</i><br />
<i>INFO: Execute project builders</i><br />
<i>INFO: Execute project builders (done) | time=0ms</i><br />
<i>INFO: Project key: StaticCodeAnalysis.project</i><br />
<i>INFO: Base dir: C:\temp</i><br />
<i>INFO: Working dir: C:\temp\.scannerwork</i><br />
<i>INFO: Load project settings</i><br />
<i>INFO: Load project settings (done) | time=16ms</i><br />
<i>INFO: Load project repositories</i><br />
<i>INFO: Load project repositories (done) | time=47ms</i><br />
<i>INFO: Load quality profiles</i><br />
<i>INFO: Load quality profiles (done) | time=63ms</i><br />
<i>INFO: Load active rules</i><br />
<i>INFO: Load active rules (done) | time=1922ms</i><br />
<i>INFO: Load metrics repository</i><br />
<i>INFO: Load metrics repository (done) | time=32ms</i><br />
<i>WARN: SCM provider autodetection failed. Please use "sonar.scm.provider" to define SCM of your project, or disable the SCM Sensor in the project settings.</i><br />
<i>INFO: Language is forced to tsql</i><br />
<i>INFO: Indexing files...</i><br />
<i>INFO: Project configuration:</i><br />
<i>INFO: 23 files indexed</i><br />
<i>INFO: Quality profile for tsql: Sonar Way</i><br />
<i>INFO: ------------- Run sensors on module Static Code Analysis project</i><br />
<i>INFO: Sensor JaCoCo XML Report Importer [jacoco]</i><br />
<i>INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=0ms</i><br />
<i>INFO: Sensor MsIssuesLoaderSensor [tsqlopen]</i><br />
<i>INFO: Found 0 issues</i><br />
<i>INFO: Sensor MsIssuesLoaderSensor [tsqlopen] (done) | time=15ms</i><br />
<i>INFO: Sensor CodeGuardIssuesLoaderSensor [tsqlopen]</i><br />
<i>INFO: SQL Code guard path is empty, trying to search directories instead</i><br />
<i>INFO: Found 0 issues</i><br />
<i>INFO: Sensor CodeGuardIssuesLoaderSensor [tsqlopen] (done) | time=0ms</i><br />
<i>INFO: Sensor CustomChecksSensor [tsqlopen]</i><br />
<i>WARN: Property 'sonar.tsql.customrules.paths' is not declared as multi-values/property set but was read using 'getStringArray' method. The SonarQube plugin declaring this property should be updated.</i><br />
<i>INFO: Total 1 custom rules repositories with total 15 checks</i><br />
<i>INFO: Sensor CustomChecksSensor [tsqlopen] (done) | time=21548ms</i><br />
<i>INFO: Sensor CoverageSensor [tsqlopen]</i><br />
<i>INFO: Sensor CoverageSensor [tsqlopen] (done) | time=16ms</i><br />
<i>INFO: Sensor JavaXmlSensor [java]</i><br />
<i>INFO: Sensor JavaXmlSensor [java] (done) | time=0ms</i><br />
<i>INFO: Sensor HTML [web]</i><br />
<i>INFO: Sensor HTML [web] (done) | time=15ms</i><br />
<i>INFO: Sensor Zero Coverage Sensor</i><br />
<i>INFO: Sensor Zero Coverage Sensor (done) | time=16ms</i><br />
<i>INFO: ------------- Run sensors on project</i><br />
<i>INFO: No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.</i><br />
<i>INFO: 21 files had no CPD blocks</i><br />
<i>INFO: Calculating CPD for 2 files</i><br />
<i>INFO: CPD calculation finished</i><br />
<i>INFO: Analysis report generated in 250ms, dir size=127 KB</i><br />
<i>INFO: Analysis report compressed in 51ms, zip size=40 KB</i><br />
<i>INFO: Analysis report uploaded in 47ms</i><br />
<i>INFO: ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard?id=StaticCodeAnalysis.project</i><br />
<i>INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report</i><br />
<i>INFO: More about the report processing at http://localhost:9000/api/ce/task?id=AWjjFKvAkkLV5J16bDDx</i><br />
<i>INFO: Analysis total time: 26.228 s</i><br />
<i>INFO: ------------------------------------------------------------------------</i><br />
<i>INFO: EXECUTION SUCCESS</i><br />
<i>INFO: ------------------------------------------------------------------------</i><br />
<i>INFO: Total time: 28.017s</i><br />
<i>INFO: Final Memory: 36M/1173M</i><br />
<i>INFO: ------------------------------------------------------------------------</i><br />
<i><br /></i>
<i>C:\temp></i><br />
<br />
<br />
When you get the prompt back, it's time to go to the http://localhost:9000/projects URL<br />
<br />
You should have 1 project there, the name matches what we had in our properties file<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">sonar.projectName=Static Code Analysis project</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoQnDyWbOIFmhmUivhW18h2KjIglMZHzmZq433M_9vh6diil8KGV_FJY-qBM_FiJcU6C4YcZRkJafHCc7HSLbrTTkJVofjRBk_LkVsB7uxukVRZ2TMllgBlb7V07BSimEBLCqz/s1600/Cube1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="483" data-original-width="1208" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoQnDyWbOIFmhmUivhW18h2KjIglMZHzmZq433M_9vh6diil8KGV_FJY-qBM_FiJcU6C4YcZRkJafHCc7HSLbrTTkJVofjRBk_LkVsB7uxukVRZ2TMllgBlb7V07BSimEBLCqz/s640/Cube1.PNG" width="640" /></a></div>
<br />
<br />
When you click on the project, you will get some information about bugs, code smells and duplication<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5X7RjQjLGgQvrrYWJ-rps_b05dksn0U2UTlfyZmbyddAtAlfMMMeRpuLG3iT_YI2wJQGtwbCqSi773d2OD5JXVzQb0yY5eojMCrYTLHx7Hi6HVCbvdD8FwXWO3ivYMdmY8FON/s1600/Cube2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="848" data-original-width="1600" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5X7RjQjLGgQvrrYWJ-rps_b05dksn0U2UTlfyZmbyddAtAlfMMMeRpuLG3iT_YI2wJQGtwbCqSi773d2OD5JXVzQb0yY5eojMCrYTLHx7Hi6HVCbvdD8FwXWO3ivYMdmY8FON/s640/Cube2.PNG" width="640" /></a></div>
<br />
Clicking on code smells brings back the following.. you can then act on those or not<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTJiYVZ2uUsSgh41mWAtlDPZQza0ociXR3dpVLWkdNF7DBiaWHiOhTwjDWV0Gz1sBYMmysiGFBeqF_JmeqD19_tSKhQImuCME-YGNEcVX_2ieL5b_7bCEumy0c3_kXs5eN3Gm1/s1600/Cube3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="669" data-original-width="1146" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTJiYVZ2uUsSgh41mWAtlDPZQza0ociXR3dpVLWkdNF7DBiaWHiOhTwjDWV0Gz1sBYMmysiGFBeqF_JmeqD19_tSKhQImuCME-YGNEcVX_2ieL5b_7bCEumy0c3_kXs5eN3Gm1/s640/Cube3.PNG" width="640" /></a></div>
<br />
<br />
I added 2 of my own bad procs to see what it would flag<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">create</span> proc BadProc
<span style="color: #008800; font-weight: bold;">as</span>
<span style="color: #008800; font-weight: bold;">select</span> * <span style="color: #008800; font-weight: bold;">from</span> Person.Address
<span style="color: #008800; font-weight: bold;">order</span> <span style="color: #008800; font-weight: bold;">by</span> <span style="color: #0000dd; font-weight: bold;">2</span>,<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<br />
<br />
I also added this one Unique_Login_IPs, you can grab it here <a href="https://social.msdn.microsoft.com/Forums/en-US/55cfe1b0-402a-4468-bf7a-cc0966d4a487/faster-way-to-do-this">https://social.msdn.microsoft.com/Forums/en-US/55cfe1b0-402a-4468-bf7a-cc0966d4a487/faster-way-to-do-this</a><br />
<br />
As you can see we got some warnings for those procs<br />
<br />
SELECT *.. <i>No need to comment on this one</i><br />
No ASC/DESC in the order by... <i>this defaults to ASC anyway but I guess for clarity it's better to specify ASC</i><br />
Positional reference is used... <i>I do this all the time with ad-hoc queries but I don't do it with procs</i><br />
<br />
Non-sargeable argument found - column referenced in a function.<br />
<br />
That is this line<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">WHERE</span> (<span style="color: #008800; font-weight: bold;">method</span> = <span style="background-color: #fff0f0;">'LOGIN'</span>) <span style="color: #008800; font-weight: bold;">AND</span> (<span style="color: #008800; font-weight: bold;">YEAR</span>(logged) = @year1) <span style="color: #008800; font-weight: bold;">AND</span> (<span style="color: #008800; font-weight: bold;">MONTH</span>(logged) = <span style="color: #0000dd; font-weight: bold;">3</span>)) <span style="color: #008800; font-weight: bold;">as</span> tmpy1_3</pre>
<br />
This you would ideally rewrite by doing something like first creating the variable @startdate and let it have the value @year.03/01 in other words '20190301'<br />
<br />
Then the WHERE clause would be something like that<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">WHERE</span> (<span style="color: #008800; font-weight: bold;">method</span> = <span style="background-color: #fff0f0;">'LOGIN'</span>) <span style="color: #008800; font-weight: bold;">AND </span>logged >= @startdate <span style="color: #008800; font-weight: bold;">and</span> logged < dateadd(mm,<span style="color: #0000dd; font-weight: bold;">1</span>,@startdate) </pre>
<br />
That is all for this post. Of course you can do some of this stuff with other tools and even with policy management. But if you use SQL Server and many languages, you could do static code analysis from one tool<br />
<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-35133484986282208322019-02-12T12:26:00.000-08:002019-02-13T06:59:29.236-08:00Scripting out procs and user defined functions with PowerShell<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
I decided to take SonarCube for a spin to run some static code analysis. In order to do that I needed some code that I can display here without breaking laws.<br />
<br />
I a real world, you would just point SonarCube to your code repository, but in order to show you how to run it so that you can follow along, I decided to go this route<br />
<br />
I decided to use the AdventureWorks database to script out some procs and functions. If you want to follow what I am doing here, grab the backup from here: <a href="https://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks">https://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks</a><br />
<br />
On your C drive create a folder named DB, in the DB folder create 2 folders, one name data and the other log<br />
<br />
To restore the DB you can run this command (assuming your backup is in the c:\temp directory<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">USE [master]
RESTORE <span style="color: #008800; font-weight: bold;">DATABASE</span> [AdventureWorks2017]
<span style="color: #008800; font-weight: bold;">FROM</span> DISK = N<span style="background-color: #fff0f0;">'C:\temp\AdventureWorks2017.bak'</span> <span style="color: #008800; font-weight: bold;">WITH</span> FILE = <span style="color: #0000dd; font-weight: bold;">1</span>,
<span style="color: #008800; font-weight: bold;">MOVE</span> N<span style="background-color: #fff0f0;">'AdventureWorks2017'</span>
<span style="color: #008800; font-weight: bold;">TO</span> N<span style="background-color: #fff0f0;">'C:\DB\DATA\AdventureWorks2017.mdf'</span>,
<span style="color: #008800; font-weight: bold;">MOVE</span> N<span style="background-color: #fff0f0;">'AdventureWorks2017_log'</span>
<span style="color: #008800; font-weight: bold;">TO</span> N<span style="background-color: #fff0f0;">'C:\DB\LOG\AdventureWorks2017_log.ldf'</span>,
NOUNLOAD, STATS = <span style="color: #0000dd; font-weight: bold;">5</span></pre>
<br />
Now It's time to script out the procs and user defined functions<br />
<br />
But first we need a place to store them<br />
<br />
In my case I decided to create 2 folders in the c:\temp directory<br />
StoredProcedures<br />
UserDefinedFunctions<br />
<br />
Now it's time to script out the procs and user defined functions, I will be using Powershell from that, you will need to install the sql server module, you can download it here<br />
<br />
<a href="https://docs.microsoft.com/en-us/sql/powershell/download-sql-server-ps-module?view=sql-server-2017">https://docs.microsoft.com/en-us/sql/powershell/download-sql-server-ps-module?view=sql-server-2017</a><br />
<br />
Follow the instruction if you get any errors.<br />
<br />
Now it's time to run the script, you will need to run powershell as an administrator<br />
<br />
You will need to change Machinename\sql2019 to your machine and instance name<br />
<br />
The script is simple.. it's for a one time use.. if you need to run the script repeatedly, you probably want to make it so you can rerun it for different databases and servers, so no hardcoding :-)<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">Import-Module SqlServer -Version <span style="color: #6600ee; font-weight: bold;">21</span>.<span style="color: #6600ee; font-weight: bold;">0</span>.<span style="color: #6600ee; font-weight: bold;">17279</span>
<span style="color: #008800; font-weight: bold;">cd</span> SQLSERVER:\SQL\MAchinename\sql<span style="color: #6600ee; font-weight: bold;">2019</span>\Databases\AdventureWorks<span style="color: #6600ee; font-weight: bold;">2017</span>\StoredProcedures
foreach ($tbl in Get-ChildItem )
{
$k=<span style="background-color: #fff0f0;">"C:\Temp\StoredProcedures\"</span> + $($tbl.Schema) + <span style="background-color: #fff0f0;">"."</span> + $($tbl.name) + <span style="background-color: #fff0f0;">".SQL"</span>
$tbl.Script() > $k
}
<span style="color: #008800; font-weight: bold;">cd</span> ..\UserDefinedFunctions
foreach ($tbl in Get-ChildItem )
{
$k=<span style="background-color: #fff0f0;">"C:\Temp\UserDefinedFunctions\"</span> + $($tbl.Schema) + <span style="background-color: #fff0f0;">"."</span> + $($tbl.name) + <span style="background-color: #fff0f0;">".SQL"</span>
$tbl.Script() > $k</pre>
<br />
<br />
That's all for the script.. if it ran successfully, you should see a bunch of procs and user defined functions in their directories. Here is a view of the functions<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_q94EPZFXkIdKNb1geQYSRco_2DHyJNILwz-AGqhyphenhyphenKWyUAjUsQUoO4gUi-ZHvTGt9QoIW040SCvOQepwWmjzAmNsJnBoUCpRyD2QylvNhLDZEKvMh80VSVb18NwHyWnQo0s7q/s1600/UserdefinedFunction.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="409" data-original-width="725" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_q94EPZFXkIdKNb1geQYSRco_2DHyJNILwz-AGqhyphenhyphenKWyUAjUsQUoO4gUi-ZHvTGt9QoIW040SCvOQepwWmjzAmNsJnBoUCpRyD2QylvNhLDZEKvMh80VSVb18NwHyWnQo0s7q/s640/UserdefinedFunction.PNG" width="640" /></a></div>
<br />
Next up..<a href="https://sqlservercode.blogspot.com/2019/02/using-sonarqube-sonarqube-scanner-and-sonar-tsql-plugin-to-run-static-code-analysis.html">installing SonarQube, SonarQube Scanner and the sonar-tsql-plugin</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-49455528742225581522019-02-04T06:39:00.001-08:002019-02-13T06:59:45.123-08:00After 20+ years in IT .. I finally discovered this... Originally I was not going to write this post, but after I found out that several other people didn't know this I figured what the heck, why not, maybe this will help someone else as well<br />
<br />
Last week I was on a remote session with 2 clients, each run the Advent program . The team I am part of provides a script to run the advent (APX or Axys) executable. This will then generate the portfolios, composites, price, security master, splits and other files. We then zip it up and sftp it over for ingestion so that we can run analytics and attribution<br />
<br />
During these calls I interact with system administrators because usually the need to give permissions so that the script runs correctly<br />
<br />
None of these admins knew that what I will show you existed. All the co-workers I asked didn't know this either (This could be because they are developers and not admins)<br />
<br />
<br />
<br />
Back in the day (win 98 or perhaps NT 4), there was a windows powertool that you could install and if you right clicked on a folder you would get an option to open a command window and it would be in the path that you right clicked on<br />
<br />
Those power tools don't exist anymore and you could do the same by hacking the registry, it's like a 16 step process<br />
<br />
But there is a faster way.....<br />
<br />
So what I usually did before 2 months ago is that I would select the path<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgemfWf6YPTwuOzBT4qsI9ye1Vvy4rAeickCaXkPkEAgtLhCYR6jzwtlpfOdSR4ktxGhB1DBBX1iiqIYfYZgoFi7OrZyHh4U-jrLq17T5EWICnjjnay0wZn-23s_m93A3M4RqYa/s1600/CMD1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="863" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgemfWf6YPTwuOzBT4qsI9ye1Vvy4rAeickCaXkPkEAgtLhCYR6jzwtlpfOdSR4ktxGhB1DBBX1iiqIYfYZgoFi7OrZyHh4U-jrLq17T5EWICnjjnay0wZn-23s_m93A3M4RqYa/s640/CMD1.PNG" width="640" /></a></div>
<br />
And then I would open a command prompt, type CD and then paste the path...not too complicated<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioAfrtjIW-s_VDbE-K_44BEDCuagtth7QwDl8Hlek2pO3ANG0zzWjieZ6kIpOeql0NSJDczNZypQxeN49yYdyZ6svx1anOJLCdGQWQtHi48jWxe2PRigYllOEnXKm_ntoDkYPc/s1600/cmd2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="180" data-original-width="788" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioAfrtjIW-s_VDbE-K_44BEDCuagtth7QwDl8Hlek2pO3ANG0zzWjieZ6kIpOeql0NSJDczNZypQxeN49yYdyZ6svx1anOJLCdGQWQtHi48jWxe2PRigYllOEnXKm_ntoDkYPc/s640/cmd2.PNG" width="640" /></a></div>
<br />
But here is the faster way.... instead of copying the path...just type in cmd in the address bar and hit enter<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwNy0LMtfJemevDEK25OYCtZwqHq-yDxoACmf_88bu9qyhzyn2vcig-LbajXX12_fZ25BVpmgoc6a6q6jkP1ZmOs3fr83dRNx5CfPhDudg_6tx3cN91cd9cDkpw_3hes5sHd8f/s1600/cmd3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="435" data-original-width="771" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwNy0LMtfJemevDEK25OYCtZwqHq-yDxoACmf_88bu9qyhzyn2vcig-LbajXX12_fZ25BVpmgoc6a6q6jkP1ZmOs3fr83dRNx5CfPhDudg_6tx3cN91cd9cDkpw_3hes5sHd8f/s640/cmd3.PNG" width="640" /></a></div>
<br />
Boom shakalaka... a command prompt is opened immediately and you are in the same path<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhutmtPXkKQmk-bDP5hXmgVbs0zp32H-83ynJMOkLK9Mnw9VHul_mmi61wpZr3c9QmSN7F8NcUPo5vDcd5PlulBWRD_zcpDL0_QC5ThE8XGyAZRZ7TJYHKQcNbWMIiiLTi5Qqbd/s1600/cmd4.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="284" data-original-width="757" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhutmtPXkKQmk-bDP5hXmgVbs0zp32H-83ynJMOkLK9Mnw9VHul_mmi61wpZr3c9QmSN7F8NcUPo5vDcd5PlulBWRD_zcpDL0_QC5ThE8XGyAZRZ7TJYHKQcNbWMIiiLTi5Qqbd/s640/cmd4.PNG" width="640" /></a></div>
<br />
<br />
Did you know this also works when you type Powershell in the address bar, <a href="https://twitter.com/erikdarlingdata">Eric Darling</a> left me a comment on twitter informing me that it works with powershell as well<br />
<br />
Here is what you see after typing it<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX8-HXDnMamHLPzcxV5biZ2O_Dh7ftDIvH_1jIKdxQ5w-FKwD4LE4839L3n9kNArWmgs0buhhsomw861LZvlxCkg_6-gutJvveCsxPW8L0XkQU0tDJmFG7DX7JhO8fevkQycDY/s1600/cmd5.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="233" data-original-width="764" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX8-HXDnMamHLPzcxV5biZ2O_Dh7ftDIvH_1jIKdxQ5w-FKwD4LE4839L3n9kNArWmgs0buhhsomw861LZvlxCkg_6-gutJvveCsxPW8L0XkQU0tDJmFG7DX7JhO8fevkQycDY/s640/cmd5.PNG" width="640" /></a></div>
<br />
<br />
<br />
So there you have it... hopefully it will save you some minutes of valuable time in a year<br />
<br />
Also if you knew about this or did not know..leave a comment and let me know<br />
<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com33tag:blogger.com,1999:blog-16771259.post-91695448286079609762019-01-08T07:43:00.001-08:002019-01-08T12:32:46.298-08:00Print.. the disruptor of batch deletes in SQL<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
<br />
Someone had an issue where a batched delete script was not deleting anything. I looked over some code in our repository and noticed two patterns the way queries are written to handle batch deletes<br />
<br />
One is a while loop that runs while @@rowcount is greater than 0<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">WHILE @@rowcount > <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP (<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">END</span></pre>
<br />
<br />
The other way is to run a while loop which is always true and then check if @@rowcount is 0, if it is 0 then break out of the loop<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"> WHILE <span style="color: #0000dd; font-weight: bold;">1</span> = <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP(<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
IF @@ROWCOUNT = <span style="color: #0000dd; font-weight: bold;">0</span>
BREAK
<span style="color: #008800; font-weight: bold;">END</span></pre>
<br />
<br />
I have always used WHILE @@rowcount > 0 but you have to be careful because @@rowcount could be 0 when your while loop starts<br />
<br />
Let's take a look at an example. <i>This is a simplified example without a where clause..but let's say you have to delete several million rows from a table with many more millions of rows and the table is replicated... in that case you want to batch the deletes so that your log file doesn't fill up, replication has a chance to catch up and in general the deletes should run faster</i><br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #0000dd; font-weight: bold;">20000</span> row_number() OVER(<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> t1.id) <span style="color: #008800; font-weight: bold;">AS</span> SomeId,
getutcdate() <span style="color: #008800; font-weight: bold;">AS</span> SomeDate, newid() <span style="color: #008800; font-weight: bold;">AS</span> SomeValue
<span style="color: #008800; font-weight: bold;">INTO</span> SomeTable
<span style="color: #008800; font-weight: bold;">FROM</span> sys.sysobjects t1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> sys.sysobjects t2
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> SomeTable <span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #0000dd; font-weight: bold;">1</span>= <span style="color: #0000dd; font-weight: bold;">0</span>
WHILE @@rowcount > <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP (<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable </pre>
<div>
<br /></div>
<div>
<pre style="color: #333333; line-height: 16.25px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> SomeTable <span style="color: #888888;">-- Added here as cleanup in case people run the example</span></pre>
</pre>
</div>
<div>
<br /></div>
<div>
This is of course a silly example because why would you do a count like that against a different table before a delete</div>
<div>
<br /></div>
<div>
But what if you had this instead, you put a nice print statement there so that from the output you see when it started and you would also see the rowcounts?</div>
<div>
<br /></div>
<div>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #0000dd; font-weight: bold;">20000</span> row_number() OVER(<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> t1.id) <span style="color: #008800; font-weight: bold;">AS</span> SomeId,
getutcdate() <span style="color: #008800; font-weight: bold;">AS</span> SomeDate, newid() <span style="color: #008800; font-weight: bold;">AS</span> SomeValue
<span style="color: #008800; font-weight: bold;">INTO</span> SomeTable
<span style="color: #008800; font-weight: bold;">FROM</span> sys.sysobjects t1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> sys.sysobjects t2
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable
PRINT<span style="background-color: #fff0f0;">' Starting my update now....'</span>
WHILE @@rowcount > <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP (<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable </pre>
</div>
<div>
<br /></div>
<div>
<pre style="color: #333333; line-height: 16.25px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> SomeTable <span style="color: #888888;">-- Added here as cleanup in case people run the example</span></pre>
</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
</div>
<div>
<br />
<br />
The count is 20000 before and after the loop, nothing got delete, this is because <b>a print statement will reset @@rowcount to 0</b>. </div>
<div>
<br /></div>
<div>
Take a look by running this simple set of queries</div>
<div>
<br /></div>
<div>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #008800; font-weight: bold;">UNION</span> <span style="color: #008800; font-weight: bold;">ALL</span> <span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #0000dd; font-weight: bold;">2</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @@rowcount <span style="color: #008800; font-weight: bold;">as</span> <span style="background-color: #fff0f0;">'Rowcount'</span>
PRINT <span style="background-color: #fff0f0;">'1'</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @@rowcount <span style="color: #008800; font-weight: bold;">as</span> <span style="background-color: #fff0f0;">'RowcountAfterPrint'</span></pre>
</div>
<div>
<div>
<br /></div>
<div>
Here is what the output looks like</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVRCNb8t_mqRoHM1sEI3s8BvDjhDgYyxULmzlOvFev1Yp32NeGdSm31ze6vZB1vFZr9-WAh4njunfnP66Wvdv4wz5c2xjMiDaMWW7OcGkoF_qmxgDvvMtfP3uyzInudLJZJowC/s1600/Rowcount.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="257" data-original-width="262" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVRCNb8t_mqRoHM1sEI3s8BvDjhDgYyxULmzlOvFev1Yp32NeGdSm31ze6vZB1vFZr9-WAh4njunfnP66Wvdv4wz5c2xjMiDaMWW7OcGkoF_qmxgDvvMtfP3uyzInudLJZJowC/s400/Rowcount.PNG" width="400" /></a></div>
</div>
</div>
<div>
<br /></div>
<div>
After the PRINT line @@rowcount is reset back to 0</div>
<div>
<br /></div>
<div>
So if you want to use a while loop while checking @@rowcount, do this instead by running the delete first once outside the loop</div>
<div>
<br /></div>
<div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #0000dd; font-weight: bold;">20000</span> row_number() OVER(<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> t1.id) <span style="color: #008800; font-weight: bold;">AS</span> SomeId,
getutcdate() <span style="color: #008800; font-weight: bold;">AS</span> SomeDate, newid() <span style="color: #008800; font-weight: bold;">AS</span> SomeValue
<span style="color: #008800; font-weight: bold;">INTO</span> SomeTable
<span style="color: #008800; font-weight: bold;">FROM</span> sys.sysobjects t1
<span style="color: #008800; font-weight: bold;">CROSS</span> <span style="color: #008800; font-weight: bold;">JOIN</span> sys.sysobjects t2
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable
PRINT<span style="background-color: #fff0f0;">' Starting my update now....'</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP (<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
WHILE @@rowcount > <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> TOP (<span style="color: #0000dd; font-weight: bold;">5000</span>)
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">from</span> SomeTable </pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<pre style="color: #333333; line-height: 16.25px;"><pre style="line-height: 16.25px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> SomeTable <span style="color: #888888;">-- Added here as cleanup in case people run the example</span></pre>
</pre>
</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
If you run the delete this way if there was something to delete, the while loop would be entered, if the table was empty then there would no need to enter the while loop<br />
<br />
Also keep in mind that it is not just PRINT that will reset @@rowcount back to 0.<br />
<br />
From <a href="https://docs.microsoft.com/en-us/sql/t-sql/functions/rowcount-transact-sql?view=sql-server-2017">Books On Line</a>:<br />
<br />
<span style="background-color: white; font-family: "segoe ui" , "segoeui" , "segoe wp" , "helvetica neue" , "helvetica" , "tahoma" , "arial" , sans-serif; font-size: 16px;"><i>Statements such as USE, SET <option>, DEALLOCATE CURSOR, CLOSE CURSOR, BEGIN TRANSACTION, or COMMIT TRANSACTION reset the ROWCOUNT value to 0.</i></span></div>
</div>
<div>
<br /></div>
<div>
That's all... hopefully this helps someone out in the future if they notice nothing gets deleted</div>
<div>
<br /></div>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-16771259.post-35680688137250577572019-01-04T08:58:00.000-08:002019-03-18T06:20:06.938-07:00Proactive notifications<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">It has been a while since I wrote some of my best practices posts. I decided to revisit these posts again to see if anything has changed, I also wanted to see if I could add some additional info.</span><br />
<div style="background-color: white;">
</div>
<br style="background-color: white;" />
<br style="background-color: white;" />
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"> Today we are going to look at proactive notifications</span><br />
<br />
In the <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/business-intelligence-1/sql-server-maintenance" href="http://sqlservercode.blogspot.com/2019/01/sql-server-maintenance.html">SQL Server Maintenance</a> post from yesterday I touched upon proactive notifications a little, today I want to dive a little deeper into this subject.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
The last thing you want to hear as a DBA is ny of the following things from the end users or developers</div>
<ul style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<li>The transaction log is full</li>
<li>The database is very slow</li>
<li>The latest backup we have is 9 days old</li>
<li>The table that was created has 2 extra columns this morning</li>
<li>Everything is locked up can't get any results back from a query</li>
<li>Deadlocks are occurring</li>
</ul>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
What you really want to have at your shop is a tool like <a data-mce-href="http://www.quest.com/foglight-for-sql-server/" href="http://www.quest.com/foglight-for-sql-server/">Quest Foglight</a>, <a data-mce-href="http://www.confio.com/performance/sql-server/ignite/" href="https://www.solarwinds.com/database-performance-monitoring-software">Solarwinds</a>, <a data-mce-href="http://www.red-gate.com/products/dba/sql-monitor/" href="http://www.red-gate.com/products/dba/sql-monitor/">Red Gate SQL Monitor</a> or similar. The benefit of these tools is that there is a central location where you can look at all the alerts at a glance. You get a lot of stuff out of the box and all you have to do is tell it what server to start monitoring. I would suggest to start using the trial version to see if it is something that would be beneficial for your organization.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Of course you can roll your own solution as well, this will involve work and unless your time is worthless or you are bored out of your mind after work I wouldn't do it.</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Utilize the logs</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
You need to scan the errorlog periodically to see if there are errors, you can automate this, no need to start opening log files every 5 minutes. create a SQL Agent job that runs every 5 minutes and checks if there are any errors since it last ran. You can use the xp_readerrorlog proc to read the error log from with sql server with T-SQL.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here is a small example of what you can do if you have this in a SQL Agent job that runs every 5 minutes or so, you can of course email yourself the results, dump the result into a table that is perhaps shown on a dashboard in the office, there are many possibilities.<br />
<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #888888;">--This will hold the rows</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #ErrorLog (LogDate datetime, ProcessInfo <span style="color: #007020;">VarChar</span>(<span style="color: #0000dd; font-weight: bold;">10</span>), </pre>
<pre style="line-height: 16.25px;">ErrorMessage <span style="color: #007020;">VarChar</span>(<span style="color: #008800; font-weight: bold;">Max</span>))
<span style="color: #888888;">-- Dump the errorlog into the table</span>
<span style="color: #008800; font-weight: bold;">INSERT</span> <span style="color: #008800; font-weight: bold;">INTO</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">EXEC</span> master.dbo.xp_readerrorlog
<span style="color: #888888;">-- Delete everything older than 5 minutes</span>
<span style="color: #888888;">-- ideally you will store the max date when it ran last</span>
<span style="color: #008800; font-weight: bold;">DELETE</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">WHERE</span> LogDate < DATEADD(mi,-<span style="color: #0000dd; font-weight: bold;">5</span>,GETDATE())
<span style="color: #888888;">-- Some stuff you want to check for</span>
<span style="color: #888888;">-- Failed backups...you want to know this</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">WHERE</span> ErrorMessage <span style="color: #008800; font-weight: bold;">LIKE</span><span style="background-color: #fff0f0;">'BACKUP failed%'</span>
<span style="color: #888888;">-- Why does it take so looong to grow a file, maybe rethink your settings</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">WHERE</span> ErrorMessage <span style="color: #008800; font-weight: bold;">LIKE</span><span style="background-color: #fff0f0;">'Autogrow of file%'</span>
<span style="color: #888888;">-- What is going on any backups or statistic updates running at this time?</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">WHERE</span> ErrorMessage <span style="color: #008800; font-weight: bold;">LIKE</span><span style="background-color: #fff0f0;">'SQL Server has encountered %occurrence(s) of I/O requests taking longer than%'</span>
<span style="color: #888888;">-- My mirror might not be up to date</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #ErrorLog
<span style="color: #008800; font-weight: bold;">WHERE</span> ErrorMessage <span style="color: #008800; font-weight: bold;">LIKE</span><span style="background-color: #fff0f0;">'The alert for ''unsent log'' has been raised%'</span>
<span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #ErrorLog </pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
Those are just small samples, you might want to look for other kind of messages from the errorlog</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
The transaction log is full</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
You want to make sure that you know you are running out of space before you run out of space. I covered this in the <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/business-intelligence-1/sql-server-maintenance" href="http://sqlservercode.blogspot.com/2019/01/sql-server-maintenance.html">SQL Server Maintenance</a> post Take a look at the sections <em>Make sure that you have enough space left on the drives</em> and <em>Make sure that you have enough space left for the filegroups</em> In those two section I described what to look for and also supplied code that you can then plug into your own solution</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
The database is very slow</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
This complaint you hear every now and then, I have seen this from time to time. There are several things that could be happening, here is a list</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Someone decided to take a backup of that 1 TB database in the middle of the day<br />
The update statistics job is still running<br />
Statistics are stale and haven't been updated in a long time<br />
The virus scan is running amok and nobody told it to ignore the database files<br />
Someone decided to query all the data all at once</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
If you have a tool like <a data-mce-href="http://www.quest.com/foglight-for-sql-server/" href="http://www.quest.com/foglight-for-sql-server/">Quest Foglight</a>, <a data-mce-href="http://www.confio.com/performance/sql-server/ignite/" href="http://www.confio.com/performance/sql-server/ignite/">Confio Ignite</a>, <a data-mce-href="http://www.red-gate.com/products/dba/sql-monitor/" href="http://www.red-gate.com/products/dba/sql-monitor/">Red Gate SQL Monitor</a> or similar then you can see what query ran at what time, what it did and how long it ran.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
You can of course also use sp_who2, BlkBy column and DBCC INPUTBUFFER to see what is going on</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
If you like to use Dynamic Management Views, then take a look at Glenn Berry's <a data-mce-href="http://sqlserverperformance.wordpress.com/2012/12/06/sql-server-2005-diagnostic-information-queries-dec-2012/" href="https://www.sqlskills.com/blogs/glenn/category/dmv-queries/">SQL Server 2005 Diagnostic Information Queries </a> posts, there is a .sql file in each post with all kind of queries to discover all kinds of stuff about your server.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
It could also be that your hardware is having issues, make sure the IOs look good and check the eventlog for any clues.</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
The latest backup we have is 9 days old</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
The following query will give you for all the databases the last time it was backed up or display NEVER if it wasn't backed up<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> s.Name <span style="color: #008800; font-weight: bold;">AS</span> DatabaseName,<span style="background-color: #fff0f0;">'Database backup was taken on '</span> +
<span style="color: #008800; font-weight: bold;">CASE</span> <span style="color: #008800; font-weight: bold;">WHEN</span> <span style="color: #008800; font-weight: bold;">MAX</span>(b.backup_finish_date) <span style="color: #008800; font-weight: bold;">IS</span> <span style="color: #008800; font-weight: bold;">NULL</span> <span style="color: #008800; font-weight: bold;">THEN</span> <span style="background-color: #fff0f0;">'NEVER!!!'</span> <span style="color: #008800; font-weight: bold;">ELSE</span>
<span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">12</span>), (<span style="color: #008800; font-weight: bold;">MAX</span>(b.backup_finish_date)), <span style="color: #0000dd; font-weight: bold;">101</span>) <span style="color: #008800; font-weight: bold;">END</span> <span style="color: #008800; font-weight: bold;">AS</span> LastBackUpTime
<span style="color: #008800; font-weight: bold;">FROM</span> sys.sysdatabases s
<span style="color: #008800; font-weight: bold;">LEFT</span> <span style="color: #008800; font-weight: bold;">OUTER</span> <span style="color: #008800; font-weight: bold;">JOIN</span> msdb.dbo.backupset b <span style="color: #008800; font-weight: bold;">ON</span> b.database_name = s.name
<span style="color: #008800; font-weight: bold;">GROUP</span> <span style="color: #008800; font-weight: bold;">BY</span> s.Name</pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
Here is what the output will look like<br />
<br /></div>
<pre style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;">DatabaseName LastBackUpTime
-------------- ---------------------------------------
model Database backup was taken on NEVER!!!
msdb Database backup was taken on 12/10/2012
ReportServer Database backup was taken on NEVER!!!</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
<br />
As you can see that is not that great, all the databases should be backed up on a regular basis. Scroll up to the <em>Utilize the logs</em> section to see how you can check the errorlog for failed backup messages.</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Everything is locked up, you can't get any results back from a query</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Usually this indicates that there is an open transaction somewhere that has not finished or someone did the BEGIN TRAN part but never did a COMMIT or ROLLBACK.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Some people just restart the server to 'fix' the issue, of course if you do that you will never know what the root cause is and you never know when it will happen again.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
We can easily show what happens when you have an open transaction, btw don't do this on the production server.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
In 1 query window run this, replace SomeTable with a real table name.<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">BEGIN</span> TRAN
<span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #0000dd; font-weight: bold;">1</span> * <span style="color: #008800; font-weight: bold;">FROM</span> SomeTable <span style="color: #008800; font-weight: bold;">WITH</span>(UPDLOCK, HOLDLOCK)</pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
You will get a message that the query completed successfully</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
In another window run this<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> TOP <span style="color: #0000dd; font-weight: bold;">1</span> * <span style="color: #008800; font-weight: bold;">FROM</span> SomeTable <span style="color: #008800; font-weight: bold;">WITH</span>(UPDLOCK, HOLDLOCK)</pre>
<pre style="line-height: 16.25px;"></pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
That query won't return anything unless the first one is commited or rolled back<br />
<br />
Now run this query below, the first column should have the text AWAITING COMMAND<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> sys.cmd
,sys.last_batch
,lok.resource_type
,lok.resource_subtype
,DB_NAME(lok.resource_database_id)
,lok.resource_description
,lok.resource_associated_entity_id
,lok.resource_lock_partition
,lok.request_mode
,lok.request_type
,lok.request_status
,lok.request_owner_type
,lok.request_owner_id
,lok.lock_owner_address
,wat.waiting_task_address
,wat.session_id
,wat.exec_context_id
,wat.wait_duration_ms
,wat.wait_type
,wat.resource_address
,wat.blocking_task_address
,wat.blocking_session_id
,wat.blocking_exec_context_id
,wat.resource_description
<span style="color: #008800; font-weight: bold;">FROM</span> sys.dm_tran_locks lok
<span style="color: #008800; font-weight: bold;">JOIN</span> sys.dm_os_waiting_tasks wat
<span style="color: #008800; font-weight: bold;">ON</span> lok.lock_owner_address = wat.resource_address
<span style="color: #008800; font-weight: bold;">JOIN</span> sys.sysprocesses sys <span style="color: #008800; font-weight: bold;">ON</span> wat.blocking_session_id = sys.spid</pre>
<pre style="line-height: 16.25px;"></pre>
<pre style="line-height: 16.25px;"></pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
As you can see you have a blocking_session_id and a session_id, this will tell you which session_id is being blocked. You can now verify that the transaction session_id is blocking the other id</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Go back to that first command window and execute a rollback<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;">ROLLBACK</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
The query that had that second select should now be done as well, if you run that query that checks for the waits it should be clean as well.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Of course you could have done the same exercise by running sp_who2, looking at the BlkBy column, finding out what that session is doing by running DBCC INPUTBUFFER(session_id) with that session_id</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Deadlocks are occurring</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
There is already a post written on LessThanDot explaining how you can get emailed when deadlocks occur. Ted Krueger wrote that post and it can be found here: <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/proactive-deadlock-notifications" href="http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/proactive-deadlock-notifications">Proactive Deadlock Notifications</a></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Summary</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
I only touched the surface of what can be done in this post. I want you to find out if there is any monitoring being done in your shop, who gets notified? I have worked in places where the end user was the proactive notification, as long as we fixed it before the business users started to complaint life was good. Manual notifications and homebrew solutions might work for a while but when you add more and more servers and you add more people to the team this becomes laborious and error prone.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-393698828071981502019-01-03T10:26:00.002-08:002019-03-18T06:18:53.552-07:00Cursors and loops<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;">It has been a while since I wrote some of my best practices posts. I decided to revisit these posts again to see if anything has changed, I also wanted to see if I could add some additional info.</span><br />
<div style="background-color: white;">
</div>
<br style="background-color: white; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;" />
<br style="background-color: white; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;" />
<span style="background-color: white; font-family: "georgia" , "times new roman" , "bitstream charter" , "times" , serif;"> Today we are going to look at cursors</span></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Why do we hate those poor cursors?</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Let's first see why people tend to use cursors. Let's say you come from a procedural language and this is the first time you are using SQL. In the procedural language you know how to traverse a list, you of course will look for something that is similar in SQL........bingo!!! you found it...the almighty cursor....the crusher of almost all SQL Server performance. You start using it, your code works, you are happy, life is good.<br />
<br />
Now a team member tells you that the cursor is evil and should never ever be used. You are confused, if a cursor is never to be used then why is it part of the language? Well you might say the same for the GOTO statement, this exists in SQL. Edsger Dijkstra's letter <em>Go To Statement Considered Harmful</em> was published in the March 1968 Communications of the ACM.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
The reason that cursors are evil is that they tend to be slower than a set based solution. Cursors are not needed for 99% of the cases. SQL is a set based language, it works best with sets of data, not row by row processing, when you do something set based it will generally perform hundreds of times faster than using a cursor.<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Take a look at this code<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">FUNCTION</span> dbo.cursorEnroll ()
<span style="color: #008800; font-weight: bold;">RETURNS</span> <span style="color: #007020;">INT</span> <span style="color: #008800; font-weight: bold;">AS</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @studentsEnrolled <span style="color: #007020;">INT</span>
<span style="color: #008800; font-weight: bold;">SET</span> @studentsEnrolled = <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> myCursor <span style="color: #008800; font-weight: bold;">CURSOR</span> <span style="color: #008800; font-weight: bold;">FOR</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> enrollementID
<span style="color: #008800; font-weight: bold;">FROM</span> courseEnrollment
<span style="color: #008800; font-weight: bold;">OPEN</span> myCursor;
<span style="color: #008800; font-weight: bold;">FETCH</span> <span style="color: #008800; font-weight: bold;">NEXT</span> <span style="color: #008800; font-weight: bold;">FROM</span> myCursor <span style="color: #008800; font-weight: bold;">INTO</span> @studentsEnrolled
WHILE @@FETCH_STATUS = <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">SET</span> @studentsEnrolled = @studentsEnrolled+<span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">FETCH</span> <span style="color: #008800; font-weight: bold;">NEXT</span> <span style="color: #008800; font-weight: bold;">FROM</span> myCursor <span style="color: #008800; font-weight: bold;">INTO</span> @studentsEnrolled
<span style="color: #008800; font-weight: bold;">END</span>;
<span style="color: #008800; font-weight: bold;">CLOSE</span> myCursor
<span style="color: #008800; font-weight: bold;">RETURN</span> @studentsEnrolled
<span style="color: #008800; font-weight: bold;">END</span>;</pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
That whole flawed cursor logic can be replaced with one line of T-SQL<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> @studentsEnrolled = <span style="color: #008800; font-weight: bold;">COUNT</span>(*) <span style="color: #008800; font-weight: bold;">FROM</span> courseEnrollment</pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
Which one do you think will perform faster?</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
What is more evil than a cursor?</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
If cursors are evil, then what is more evil than a cursor? Nested cursors of course, especially three nested cursors. Here is an example of some horrible code where a cursor is not needed<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">PROCEDURE</span> [dbo].[sp_SomeMadeUpName]
<span style="color: #008800; font-weight: bold;">AS</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @SomeDate DATETIME
<span style="color: #008800; font-weight: bold;">SET</span> @SomeDate = <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>),getDate(),<span style="color: #0000dd; font-weight: bold;">112</span>)
<span style="color: #008800; font-weight: bold;">EXEC</span> sp_createSomeLinkedServer @SomeDate,@SomeDate,<span style="color: #0000dd; font-weight: bold;">12</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @<span style="color: #008800; font-weight: bold;">sql</span> NVARCHAR(<span style="color: #0000dd; font-weight: bold;">2000</span>), @SomeID <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">20</span>)
<span style="color: #008800; font-weight: bold;">DECLARE</span> SomeCursor <span style="color: #008800; font-weight: bold;">CURSOR</span>
<span style="color: #008800; font-weight: bold;">FOR</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">DISTINCT</span> SomeID
<span style="color: #008800; font-weight: bold;">FROM</span> SomeTable
<span style="color: #008800; font-weight: bold;">WHERE</span> getDate() <span style="color: #008800; font-weight: bold;">BETWEEN</span> SomeStart <span style="color: #008800; font-weight: bold;">and</span> SomeEnd
<span style="color: #008800; font-weight: bold;">OPEN</span> SomeCursor
<span style="color: #008800; font-weight: bold;">FETCH</span> <span style="color: #008800; font-weight: bold;">NEXT</span> <span style="color: #008800; font-weight: bold;">FROM</span> SomeCursor <span style="color: #008800; font-weight: bold;">INTO</span> @SomeID
WHILE @@FETCH_STATUS = <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
PRINT @SomeID
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = <span style="background-color: #fff0f0;">''</span>
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'DECLARE @Date DATETIME, @Value FLOAT'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'DECLARE curData CURSOR FOR'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'SELECT * '</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'FROM OPENQUERY(LinkedServerName,''SELECT Date,'</span> + RTRIM(@SomeID) + <span style="background-color: #fff0f0;">' FROM SomeTable'')'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'OPEN curData'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'FETCH NEXT FROM curData INTO @Date,@Value'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'WHILE @@FETCH_STATUS = 0'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'BEGIN'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'INSERT INTO SomeTAble'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'VALUES('''</span> + @SomeID + <span style="background-color: #fff0f0;">''',@Date,@Value)'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'FETCH NEXT FROM curData INTO @Date,@Value'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'END'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'CLOSE curData'</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @<span style="color: #008800; font-weight: bold;">sql</span> = @<span style="color: #008800; font-weight: bold;">sql</span> + N<span style="background-color: #fff0f0;">'DEALLOCATE curData'</span>
PRINT @<span style="color: #008800; font-weight: bold;">sql</span> + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">char</span>(<span style="color: #0000dd; font-weight: bold;">13</span>)
<span style="color: #008800; font-weight: bold;">EXEC</span> sp_ExecuteSQL @<span style="color: #008800; font-weight: bold;">sql</span>
<span style="color: #008800; font-weight: bold;">FETCH</span> <span style="color: #008800; font-weight: bold;">NEXT</span> <span style="color: #008800; font-weight: bold;">FROM</span> SomeCursor <span style="color: #008800; font-weight: bold;">INTO</span> @SomeID
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">CLOSE</span> SomeCursor
<span style="color: #008800; font-weight: bold;">DEALLOCATE</span> SomeCursor</pre>
<pre style="line-height: 16.25px;"></pre>
<pre style="line-height: 16.25px;"></pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Why the need of looping over the list of IDs? Join with the linked server and do all this in 3 lines of code<br />
<br />
I have seen some really horrible code with nested cursors, one example I saw was when someone needed to sum up some data, he created 3 nested cursor..the first one to loop over years, the second to loop over months and the third to loop over days. This thing ran forever<br />
<br />
All you need is to do a simple group by... for example<br />
<br />
<pre style="line-height: 16.25px;">;<span style="color: #008800; font-weight: bold;">WITH</span> cte <span style="color: #008800; font-weight: bold;">AS</span> (<span style="color: #008800; font-weight: bold;">SELECT</span> DATEADD(dd,<span style="color: #007020;">number</span>,<span style="background-color: #fff0f0;">'20190101'</span>) <span style="color: #008800; font-weight: bold;">AS</span> TheDate,<span style="color: #007020;">number</span>
<span style="color: #008800; font-weight: bold;">FROM</span> master..spt_values <span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">type</span> = <span style="background-color: #fff0f0;">'p'</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">SUM</span>(<span style="color: #007020;">number</span>) <span style="color: #008800; font-weight: bold;">as</span> Value,</pre>
<pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">YEAR</span>(TheDAte)<span style="color: #008800; font-weight: bold;">as</span> TheYear, </pre>
<pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">MONTH</span>(TheDate) <span style="color: #008800; font-weight: bold;">AS</span> TheMonth
<span style="color: #008800; font-weight: bold;">FROM</span> cte
<span style="color: #008800; font-weight: bold;">GROUP</span> <span style="color: #008800; font-weight: bold;">BY</span> <span style="color: #008800; font-weight: bold;">YEAR</span>(TheDate), <span style="color: #008800; font-weight: bold;">MONTH</span>(TheDate)
<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> TheYear,TheMonth</pre>
<pre style="line-height: 16.25px;"></pre>
<pre style="line-height: 16.25px;">Output</pre>
<pre style="line-height: 16.25px;"></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAybfZsJXjEIM7Q9bZ85DEjOrjft6t9_q9SLAhmOeFE2jL48XDRWQ14-8hrb_mpGciW4ShpTkMTUKvz0bd_sobFvislQljfdLCp_10dLhbG0u265_9PQ52A7jskZ3CLvGeNpwv/s1600/GroupBy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="342" data-original-width="219" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAybfZsJXjEIM7Q9bZ85DEjOrjft6t9_q9SLAhmOeFE2jL48XDRWQ14-8hrb_mpGciW4ShpTkMTUKvz0bd_sobFvislQljfdLCp_10dLhbG0u265_9PQ52A7jskZ3CLvGeNpwv/s400/GroupBy.PNG" width="255" /></a></div>
<pre style="line-height: 16.25px;"></pre>
</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Replacing one evil with another</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
If you are using while loops instead of cursors then you really have not replaced the cursor at all, you are still not doing a set based operation, everything is still going row by row. Aaron Bertrand has a good post here, no need for me to repeat the same <a data-mce-href="http://sqlblog.com/blogs/aaron_bertrand/archive/2012/01/26/the-fallacy-that-a-while-loop-isn-t-a-cursor.aspx" href="https://sqlblog.org/2012/01/26/bad-habits-to-kick-thinking-a-while-loop-isnt-a-cursor">Bad Habits to Kick : Thinking a WHILE loop isn't a CURSOR</a></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Loops in triggers</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Usually you will find a loop in a trigger that will call some sort of stored procedures that needs to perform some kind of task for each row affected by the trigger. In the <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/triggers-what-to-do-what" href="https://sqlservercode.blogspot.com/2017/10/triggers-when-to-use-them-when-not-to.html">Triggers, when to use them, when not to use them</a> post I already explained how to handle this scenario</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Loops in stored procedures</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here is where you will find the biggest offenders. All you have to do to find the procs with cursors is run the following piece of code<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> sys.procedures
<span style="color: #008800; font-weight: bold;">WHERE</span> OBJECT_DEFINITION((object_id) )<span style="color: #008800; font-weight: bold;">LIKE</span> <span style="background-color: #fff0f0;">'%DECLARE%%cursor%'</span></pre>
</pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
For while loops, just change the '%DECLARE%%cursor%' part to '%while%'</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Look at those procs and investigate if you can rewrite them using a SET based operation instead</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Loops for maintenance purposes</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
One of the few times I will use cursors or while loops is if I need to get information about tables or databases where I have to get information from a stored procedure.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here is an example</div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"></pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #tempSpSpaceUsed (TableName <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
<span style="color: #008800; font-weight: bold;">Rows</span> <span style="color: #007020;">INT</span>,
Reserved <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
<span style="color: #008800; font-weight: bold;">Data</span> <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
IndexSize <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">100</span>),
Unused <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">100</span>))
<span style="color: #008800; font-weight: bold;">SELECT</span> name, ROW_NUMBER() OVER(<span style="color: #008800; font-weight: bold;">ORDER</span> <span style="color: #008800; font-weight: bold;">BY</span> name) <span style="color: #008800; font-weight: bold;">AS</span> id
<span style="color: #008800; font-weight: bold;">INTO</span> #temp
<span style="color: #008800; font-weight: bold;">FROM</span> sys.tables
<span style="color: #008800; font-weight: bold;">DECLARE</span> @TableName <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">300</span>)
<span style="color: #008800; font-weight: bold;">DECLARE</span> @loopid <span style="color: #007020;">INT</span> = <span style="color: #0000dd; font-weight: bold;">1</span>, @maxID <span style="color: #007020;">int</span> = (<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">MAX</span>(id) <span style="color: #008800; font-weight: bold;">FROM</span> #temp)
WHILE @loopid <= @maxID
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @TableName = name <span style="color: #008800; font-weight: bold;">FROM</span> #temp <span style="color: #008800; font-weight: bold;">WHERE</span> id = @loopid
<span style="color: #008800; font-weight: bold;">INSERT</span> #tempSpSpaceUsed
<span style="color: #008800; font-weight: bold;">EXEC</span>(<span style="background-color: #fff0f0;">'EXEC sp_spaceused '''</span> + @TableName + <span style="background-color: #fff0f0;">''''</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @loopid +=<span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">END</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #tempSpSpaceUsed</pre>
</pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"> </pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Of course this can be simplified as well, you can just run this instead of the while loop and run the output<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">DISTINCT</span> <span style="background-color: #fff0f0;">'INSERT #tempSpSPaceUsed</span>
<span style="background-color: #fff0f0;">EXEC sp_spaceused '''</span> + [name] + <span style="background-color: #fff0f0;">''''</span>
<span style="color: #008800; font-weight: bold;">FROM</span> sys.tables</pre>
</pre>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Finally if you need more cursor goodness, take a look at these three posts which are also mentioned in the wiki article<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<a data-mce-href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-1.html" href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-1.html">The Truth About Cursors: Part I</a><br />
<a data-mce-href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-2.html" href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-2.html">The Truth About Cursors: Part II</a><br />
<a data-mce-href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-3.html" href="http://bradsruminations.blogspot.com/2010/05/truth-about-cursors-part-3.html">The Truth About Cursors: Part III</a></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-70168210732499498502019-01-01T13:28:00.000-08:002019-03-18T06:17:55.134-07:00SQL Server Maintenance<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZHnTKpVAnpguVEUBrYoCks_MuRSI4JWhmHiV3wqwomN8oOtLrU2MI5dXx5B5d8EYNPWFsP2DpYwV_J8kgVnIaHVPUlE3B8IOP0JDg1p5aZzQjZizuWKrxj6SKR58HfYn47aKe/s1600/Maintenance.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="240" data-original-width="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZHnTKpVAnpguVEUBrYoCks_MuRSI4JWhmHiV3wqwomN8oOtLrU2MI5dXx5B5d8EYNPWFsP2DpYwV_J8kgVnIaHVPUlE3B8IOP0JDg1p5aZzQjZizuWKrxj6SKR58HfYn47aKe/s1600/Maintenance.jpg" /></a></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
It has been a while since I wrote some of my best practices posts. I decided to revisit these posts again to see if anything has changed, I also wanted to see if I could add some additional info.<br />
<br />
In this post we are going to look at SQL Server maintenance<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Just like with a car or a house, you need to do maintenance on databases as well. SQL Server has gotten better over the years, there are less knobs you need to turn out of the box but maintenance is still required.<br />
<br />
<br />
In this post I will be looking at some stuff that you need to be aware of. Some of the things I will mention can be thought of as maintenance as well as regular checks. Think of a DBA as a car mechanic, instead of an oil change, tune up or checking the tire pressure, the DBA will check index fragmentation, run DBCC CHECKDB and make sure you have enough space for the database to grow for the next predetermined period.<br />
<br />
The things I will cover in this post are: fragmentation of indexes, free drives space, space in filegroups, running DBCC CHECKDB and finally making sure that you have the latest source code of your objects in a source control system.</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Check fragmentation of indexes</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
A lot of time your index will get fragmented over time if you do a lot of updates or inserts and deletes.<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Now instead of rolling your own solution, you should take a look at some of them that are out there and used by many people. Take a look at <a data-mce-href="http://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html" href="http://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html">SQL Server Index and Statistics Maintenance</a> by <a data-mce-href="http://ola.hallengren.com/" href="http://ola.hallengren.com/">Ola Hallengren</a>, You can also get the scripts from Github here: <a href="https://github.com/olahallengren/sql-server-maintenance-solution">https://github.com/olahallengren/sql-server-maintenance-solution</a><br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Check that your database is healthy by running DBCC CHECKDB</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
What does DBCC CHECKDB do? Here is the explanation from <a data-mce-href="http://msdn.microsoft.com/en-us/library/ms176064" href="http://msdn.microsoft.com/en-us/library/ms176064">Books On Line</a><br />
<em>Checks the logical and physical integrity of all the objects in the specified database by performing the following operations:</em></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
<ul>
<li>Runs DBCC CHECKALLOC on the database.</li>
<li>Runs DBCC CHECKTABLE on every table and view in the database.</li>
<li>Runs DBCC CHECKCATALOG on the database.</li>
<li>Validates the contents of every indexed view in the database.</li>
<li>Validates link-level consistency between table metadata and file system directories and files when storing varbinary(max) data in the file system using FILESTREAM.</li>
<li>Validates the Service Broker data in the database.</li>
</ul>
</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
So how frequent should you be running DBCC CHECKDB? Ideally you should be running DBCC CHECKDB as frequent as possible, do you want to find out that there is corruption when it is very difficult to fix since two weeks have passed or do you want to find out the same day so that you can fix the table immediately.<br />
<br /></div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Paul Randal who worked on DBCC CHECKDB has a whole bunch of blog posts about DBCC CHECKDB, the posts can be found here <a href="http://www.sqlskills.com/blogs/paul/category/checkdb-from-every-angle.aspx">http://www.sqlskills.com/blogs/paul/category/checkdb-from-every-angle.aspx</a><br />
<br /></div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Make sure that you have enough space left on the drives</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Running out of space on a drive is not fun stuff, suddenly you can't insert any more data into your tables because no new pages can be allocated. If you have tools in your shop like cacti then this is probably already monitored. If you don't have any tools then either get a tool or roll your own. Here is how you can get the free space fo the drives with T-SQL<br />
<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #FixedDrives(Drive <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">1</span>),MBFree <span style="color: #007020;">INT</span>)
<span style="color: #008800; font-weight: bold;">INSERT</span> #FixedDrives
<span style="color: #008800; font-weight: bold;">EXEC</span> xp_fixeddrives
<span style="color: #008800; font-weight: bold;">SELECT</span> * <span style="color: #008800; font-weight: bold;">FROM</span> #FixedDrives</pre>
</pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"></pre>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"></pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
Here is the output for one of my servers<br />
<br /></div>
<pre style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;">Drive MBFree
------------------
C 6916 -- System
D 28921 -- Apps
L 52403 -- Log
M 4962 -- System databases
T 86208 -- Temps
U 71075 -- User databases
V 212075-- User databases </pre>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
<br />
Here is a simple way of using T-SQL to create a SQL Agent job that runs every 10 minutes and will send an email if you go below the threshold that you specified. This code is very simple and is just to show you that you can do this in T-SQL. You can make it more dynamic/configurable by not hard-coding the drives or thresholds<br />
<br />
<pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">DECLARE</span> @MBFreeD <span style="color: #007020;">INT</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @MBFreeE <span style="color: #007020;">INT</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #FixedDrives(Drive <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">1</span>),MBFree <span style="color: #007020;">INT</span>)
<span style="color: #008800; font-weight: bold;">INSERT</span> #FixedDrives
<span style="color: #008800; font-weight: bold;">EXEC</span> xp_fixeddrives
<span style="color: #008800; font-weight: bold;">SELECT</span> @MBFreeD = MBFree
<span style="color: #008800; font-weight: bold;">FROM</span> #FixedDrives
<span style="color: #008800; font-weight: bold;">WHERE</span> DRIVE = <span style="background-color: #fff0f0;">'D'</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> @MBFreeE = MBFree
<span style="color: #008800; font-weight: bold;">FROM</span> #FixedDrives
<span style="color: #008800; font-weight: bold;">WHERE</span> DRIVE = <span style="background-color: #fff0f0;">'E'</span>
<span style="color: #008800; font-weight: bold;">DROP</span> <span style="color: #008800; font-weight: bold;">TABLE</span> #FixedDrives
IF @MBFreeD < <span style="color: #0000dd; font-weight: bold;">30000</span> <span style="color: #008800; font-weight: bold;">OR</span> @MBFreeE < <span style="color: #0000dd; font-weight: bold;">10000</span>
<span style="color: #008800; font-weight: bold;">BEGIN</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @Recipients <span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">8000</span>)
<span style="color: #008800; font-weight: bold;">SELECT</span> @Recipients =<span style="background-color: #fff0f0;">'SomeGroup@SomeEmail.com'</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @p_body <span style="color: #008800; font-weight: bold;">AS</span> NVARCHAR(<span style="color: #008800; font-weight: bold;">MAX</span>), @p_subject <span style="color: #008800; font-weight: bold;">AS</span> NVARCHAR(<span style="color: #008800; font-weight: bold;">MAX</span>), @p_profile_name <span style="color: #008800; font-weight: bold;">AS</span> NVARCHAR(<span style="color: #008800; font-weight: bold;">MAX</span>)
<span style="color: #008800; font-weight: bold;">SET</span> @p_subject = @@SERVERNAME + N<span style="background-color: #fff0f0;">' Drive Space is running low'</span>
<span style="color: #008800; font-weight: bold;">SET</span> @p_body = <span style="background-color: #fff0f0;">' Drive Space is running low <br><br><br>'</span> + <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>) + <span style="background-color: #fff0f0;">'Drive D has '</span>
+ <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">20</span>),@MBFreeD) + <span style="background-color: #fff0f0;">' MB left <br>'</span> + <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">13</span>) + <span style="color: #007020;">CHAR</span>(<span style="color: #0000dd; font-weight: bold;">10</span>) + <span style="background-color: #fff0f0;">'Drive E has '</span>
+ <span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">VARCHAR</span>(<span style="color: #0000dd; font-weight: bold;">20</span>),@MBFreeE) + <span style="background-color: #fff0f0;">' MB left'</span>
<span style="color: #008800; font-weight: bold;">EXEC</span> msdb.dbo.sp_send_dbmail
@recipients = @Recipients,
@body = @p_body,
@body_format = <span style="background-color: #fff0f0;">'HTML'</span>,
@subject = @p_subject
<span style="color: #008800; font-weight: bold;">END</span></pre>
</div>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Make sure that you have enough space left for the filegroups</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
In the <a data-mce-href="http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/sizing-database-files" href="http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/sizing-database-files">Sizing database files</a> I talked about the importance of sizing database files. Just like you can run out of hard drive space, you can also fill up a file used by SQL Server. here is query that will tell you how big the file is, how much space is use and how much free space is left. You can use a query like this to alert you before you run out of space<br />
<br />
<br /></div>
<pre lang="tsql" style="color: #333333; font-family: Consolas, Monaco, monospace; font-size: 16px;"><pre style="line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">SELECT</span>
a.FILEID,
[FILE_SIZE_MB] =
<span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">DECIMAL</span>(<span style="color: #0000dd; font-weight: bold;">12</span>,<span style="color: #0000dd; font-weight: bold;">2</span>),ROUND(a.<span style="color: #008800; font-weight: bold;">size</span>/<span style="color: #0000dd; font-weight: bold;">128</span>.<span style="color: #0000dd; font-weight: bold;">000</span>,<span style="color: #0000dd; font-weight: bold;">2</span>)),
[SPACE_USED_MB] =
<span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">DECIMAL</span>(<span style="color: #0000dd; font-weight: bold;">12</span>,<span style="color: #0000dd; font-weight: bold;">2</span>),ROUND(FILEPROPERTY(a.name,<span style="background-color: #fff0f0;">'SpaceUsed'</span>)/<span style="color: #0000dd; font-weight: bold;">128</span>.<span style="color: #0000dd; font-weight: bold;">000</span>,<span style="color: #0000dd; font-weight: bold;">2</span>)),
[FREE_SPACE_MB] =
<span style="color: #008800; font-weight: bold;">CONVERT</span>(<span style="color: #007020;">DECIMAL</span>(<span style="color: #0000dd; font-weight: bold;">12</span>,<span style="color: #0000dd; font-weight: bold;">2</span>),ROUND((a.<span style="color: #008800; font-weight: bold;">size</span>-FILEPROPERTY(a.name,<span style="background-color: #fff0f0;">'SpaceUsed'</span>))/<span style="color: #0000dd; font-weight: bold;">128</span>.<span style="color: #0000dd; font-weight: bold;">000</span>,<span style="color: #0000dd; font-weight: bold;">2</span>)) ,
NAME = <span style="color: #008800; font-weight: bold;">LEFT</span>(a.NAME,<span style="color: #0000dd; font-weight: bold;">35</span>),
FILENAME = <span style="color: #008800; font-weight: bold;">LEFT</span>(a.FILENAME,<span style="color: #0000dd; font-weight: bold;">60</span>)
<span style="color: #008800; font-weight: bold;">FROM</span>
dbo.sysfiles a</pre>
</pre>
<h2 style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;">
Have the latest scripts of all your objects</h2>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
You might say that you have all the code for your objects in the database. What if you want to go back to the version of the proc from 3 days ago, is it really easier to restore a 800 GB backup from 3 days ago just to get the stored proc code?<br />
<br />
Of course not, make sure that you have DDL scripts of every object in source control, your life will be much easier.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
I only touched on a couple of points here, some of the things mentioned here will also show up in the proactive notifications post in a couple of days. There is much more to maintenance than this, keep informed and make sure you understand what needs to be done.</div>
<div style="color: #333333; font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-size: 16px;">
<br />
<br />
<h2>
Some more repos for you to use</h2>
<br />
Take a look at the GitHub repositories mentioned in this post: <a href="http://sqlservercode.blogspot.com/2017/06/five-great-sql-server-github-repos-that.html">Five great SQL Server GitHub repos that every SQL Server person should check out</a> There are some good ones like dbatools and tigertoolbox</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-16556635448721977722018-11-23T11:33:00.004-08:002018-11-23T11:47:11.468-08:00Happy Fibonacci day, here is how to generate a Fibonacci sequence in SQL <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUUvY9aKt3n5aR9QkAQzQ8okTCfOAnGHIwcLLd1GjfKlsbrgBHy5xdbZOe74w0PonAar5TZcgvlHxqxJ9hDoQeYByxYqKf74Ktkllg11P-XKijfdT95KWGrW4M7lgn-8yje0Dd/s1600/Fibonacci.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="412" data-original-width="659" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUUvY9aKt3n5aR9QkAQzQ8okTCfOAnGHIwcLLd1GjfKlsbrgBHy5xdbZOe74w0PonAar5TZcgvlHxqxJ9hDoQeYByxYqKf74Ktkllg11P-XKijfdT95KWGrW4M7lgn-8yje0Dd/s400/Fibonacci.PNG" width="400" /></a></div>
<br />
<span style="font-size: x-small;">Image by <a href="https://commons.wikimedia.org/wiki/User:Jahobr" title="User:Jahobr">Jahobr</a> - <span class="int-own-work" lang="en">Own work</span>, <a href="http://creativecommons.org/publicdomain/zero/1.0/deed.en" title="Creative Commons Zero, Public Domain Dedication">CC0</a>, <a href="https://commons.wikimedia.org/w/index.php?curid=58460223">Link</a></span>
<br />
<br />
<br />
Since today is Fibonacci day I decided to to a short post about how to do generate a Fibonacci sequence in T-SQL. But first let's take a look at what a Fibonacci sequence actually is.<br />
<br />
In mathematics, the Fibonacci numbers are the numbers in the following integer sequence, called the Fibonacci sequence, and characterized by the fact that every number after the first two is the sum of the two preceding ones:<br />
<br />
1, 1, 2, 3, 5, 8, 13, 21, 34, ...<br />
<br />
Often, especially in modern usage, the sequence is extended by one more initial term:<br />
<br />
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...<br />
<br />
November 23 is celebrated as Fibonacci day because when the date is written in the mm/dd format (11/23), the digits in the date form a Fibonacci sequence: 1,1,2,3.<br />
<br />
So here is how you can generate a Fibonacci sequence in SQL, you can do it by using s recursive table expression. Here is what it looks like if you wanted to generate the Fibonacci sequence to up to a value of 1 million<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">;<span style="color: #008800; font-weight: bold;">WITH</span> Fibonacci (Prev, <span style="color: #008800; font-weight: bold;">Next</span>) <span style="color: #008800; font-weight: bold;">as</span>
(
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">UNION</span> <span style="color: #008800; font-weight: bold;">ALL</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">Next</span>, Prev + <span style="color: #008800; font-weight: bold;">Next</span>
<span style="color: #008800; font-weight: bold;">FROM</span> Fibonacci
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">Next</span> < <span style="color: #0000dd; font-weight: bold;">1000000</span>
)
<span style="color: #008800; font-weight: bold;">SELECT</span> Prev <span style="color: #008800; font-weight: bold;">as</span> Fibonacci
<span style="color: #008800; font-weight: bold;">FROM</span> Fibonacci
<span style="color: #008800; font-weight: bold;">WHERE</span> Prev < <span style="color: #0000dd; font-weight: bold;">1000000</span></pre>
<pre style="line-height: 16.25px;"></pre>
<div>
<br /></div>
<br />
<br />
That will generate a Fibonacci sequence that starts with 1, if you need a Fibonacci sequence that start with 0, all you have to do is replace the 1 to 0 in the first select statement<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><pre style="line-height: 16.25px;">;<span style="color: #008800; font-weight: bold;">WITH</span> Fibonacci (Prev, <span style="color: #008800; font-weight: bold;">Next</span>) <span style="color: #008800; font-weight: bold;">as</span>
(
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">UNION</span> <span style="color: #008800; font-weight: bold;">ALL</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="color: #008800; font-weight: bold;">Next</span>, Prev + <span style="color: #008800; font-weight: bold;">Next</span>
<span style="color: #008800; font-weight: bold;">FROM</span> Fibonacci
<span style="color: #008800; font-weight: bold;">WHERE</span> <span style="color: #008800; font-weight: bold;">Next</span> < <span style="color: #0000dd; font-weight: bold;">1000000</span>
)
<span style="color: #008800; font-weight: bold;">SELECT</span> Prev <span style="color: #008800; font-weight: bold;">as</span> Fibonacci
<span style="color: #008800; font-weight: bold;">FROM</span> Fibonacci
<span style="color: #008800; font-weight: bold;">WHERE</span> Prev < <span style="color: #0000dd; font-weight: bold;">1000000</span></pre>
</pre>
<pre style="color: #333333; line-height: 16.25px;"></pre>
<br />
Here is what it looks like in SSMS<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdwf4_hv1SizHcM6D_KxR8LS-MNKipeQNxdMsPUFTGiIaTTgwcgQLAwUExLLKCbZil-dtk_T2T-BDuJ2bN9GZTWxYbqOsjeaRIhnWNeQAOdzkScUku71ml4K1zrXWAboAnPY9/s1600/FibonacciSSMSOutput.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="907" data-original-width="1186" height="488" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdwf4_hv1SizHcM6D_KxR8LS-MNKipeQNxdMsPUFTGiIaTTgwcgQLAwUExLLKCbZil-dtk_T2T-BDuJ2bN9GZTWxYbqOsjeaRIhnWNeQAOdzkScUku71ml4K1zrXWAboAnPY9/s640/FibonacciSSMSOutput.PNG" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Happy Fibonacci day!!<br />
<br />
I created the same for PostgreSQL, the only difference is that you need to add the keyword RECURSIVE in the CTE, here is that post <a href="https://denisgobo.blogspot.com/2018/11/happy-fibonacci-day-here-is-how-to.html">Happy Fibonacci day, here is how to generate a Fibonacci sequence in PostgreSQL </a></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-16771259.post-13037006427173237542018-09-26T17:06:00.002-07:002018-09-26T17:36:27.846-07:00A little less hate for: String or binary data would be truncated in table <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s1600/sqlserver2016.PNG" imageanchor="1"><img border="0" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJyH39ojg7hnjnBdblQv-tyyI4Nown74KT9ontgcp58Nc_CF3bGMpOESENLtFbG2R7p3m5NQWmVeopuHMO_G2j4uFONifpgQAwT-UcMRkLW-1krSW_WvGZS0872nk7keB0O6Gd/s320/sqlserver2016.PNG" width="320" /></a><br />
The error String or binary data would be truncated is one of the more annoying things in SQL Server. You would insert some data and you would get back the error String or binary data would be truncated. Then you would have to spend a good amount of time to see what caused the error.<br />
<br />
I even posted about this as part of <a href="http://sqlservercode.blogspot.com/2017/01/t-sql-tuesday-86-string-or-binary-data.html">T-SQL Tuesday #86: String or binary data would be truncated</a><br />
<br />
I read the <a href="https://info.microsoft.com/ww-landing-SQLDB-Microsoft-SQL-Server-WhitePaper.html">SQL Server 2019 CTP 2 whitepaper</a> and on page 17 it has the following<br />
<br />
<blockquote class="tr_bq">
<i><b>Improve truncation message for ETL DW scenarios</b>—the error message ID 8152 String or binary data would be
truncated is familiar to many SQL Server developers and administrators who develop or maintain data movement
workloads; the error is raised during data transfers between a source and a destination with different schemas
when the source data is too large to fit into the destination data type. This error message can be time-consuming
to troubleshoot because of its lack of specificity. SQL Server 2019 introduces a new, more specific error message
for this scenario: ID 2628 String or binary data would be truncated in table '%.*ls', column '%.*ls'. Truncated value:
'%.*ls'. The new error message provides more context for the problem, simplifying the troubleshooting process. So
that it cannot break existing applications parsing message ID 8152, this new message ID 2628 is an opt-in
replacement, which can be enabled with trace flag 460. </i></blockquote>
<br />
<br />
Oh really... they fixed this? Let's take a look<br />
<br />
First I downloaded SQL Server 2019 CTP 2 and installed it. Then I created a database with a simple table, I also inserted some data that wouldn't fit<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">DATABASE</span> truncatetest
<span style="color: #008800; font-weight: bold;">GO</span>
USE truncatetest
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TABLE</span> TruncateMe(somevalue <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>),somevalue2 <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>), somedecimal <span style="color: #007020;">decimal</span>(<span style="color: #0000dd; font-weight: bold;">5</span>,<span style="color: #0000dd; font-weight: bold;">2</span>))
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">INSERT</span> TruncateMe
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="background-color: #fff0f0;">'333333'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<br />
I then received the following error message, so this is the same as in SQL Server 2018 and earlier, notice message id 8152<br />
<br />
Msg 8152, Level 16, State 30, Line 10<br />
String or binary data would be truncated.<br />
The statement has been terminated.<br />
<br />
To enable the new functionality, we need to enable trace flag 460, you can do that by running the DBCC TRACEON command like this<br />
<br />
<pre style="color: #333333; line-height: 16.25px;">DBCC TRACEON(<span style="color: #0000dd; font-weight: bold;">460</span>)</pre>
<br />
Now let's try that insert statement again<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">INSERT</span> TruncateMe
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="background-color: #fff0f0;">'333333'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
And there we go, you get the table name, the column name as well as the value, notice that the message id changed from 8152 to 2628 now<br />
<br />
Msg 2628, Level 16, State 1, Line 20<br />
String or binary data would be truncated in table 'truncatetest.dbo.TruncateMe', column 'somevalue'. Truncated value: '33333'.<br />
The statement has been terminated.<br />
<br />
<br />
So it looks it only returns the first value that generates the error, let's change the first value to fit into the column and execute the insert statement again<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">INSERT</span> TruncateMe
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="background-color: #fff0f0;">'3'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
Now you will see that the error is for the somevalue2 column<br />
<br />
<br />
Msg 2628, Level 16, State 1, Line 27<br />
String or binary data would be truncated in table 'truncatetest.dbo.TruncateMe', column 'somevalue2'. Truncated value: '44444'.<br />
The statement has been terminated.<br />
<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
What will happen if you have more than one row that fails?<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">insert</span> TruncateMe
<span style="color: #008800; font-weight: bold;">select</span> <span style="background-color: #fff0f0;">'333333'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span> <span style="color: #008800; font-weight: bold;">union</span> <span style="color: #008800; font-weight: bold;">all</span>
<span style="color: #008800; font-weight: bold;">select</span> <span style="background-color: #fff0f0;">'3'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
Here is the error<br />
<br />
Msg 2628, Level 16, State 1, Line 37<br />
String or binary data would be truncated in table 'truncatetest.dbo.TruncateMe', column 'somevalue'. Truncated value: '33333'.<br />
The statement has been terminated.<br />
<div>
<br /></div>
<div>
As you can see the error is only for the first row, not the second one</div>
<br />
What about Table Variables, will you also get an error with the column and value like for real tables?<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">declare</span> @<span style="color: #008800; font-weight: bold;">table</span> <span style="color: #008800; font-weight: bold;">table</span> (somevalue <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>),somevalue2 <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>), somedecimal <span style="color: #007020;">decimal</span>(<span style="color: #0000dd; font-weight: bold;">5</span>,<span style="color: #0000dd; font-weight: bold;">2</span>))
<span style="color: #008800; font-weight: bold;">insert</span> @<span style="color: #008800; font-weight: bold;">table</span>
<span style="color: #008800; font-weight: bold;">select</span> <span style="background-color: #fff0f0;">'333333'</span>,<span style="background-color: #fff0f0;">'444444'</span>,<span style="color: #0000dd; font-weight: bold;">5</span>.<span style="color: #0000dd; font-weight: bold;">3</span></pre>
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #0000dd; font-weight: bold;">
</span></pre>
<br />
Here is the error<br />
<br />
Msg 2628, Level 16, State 1, Line 53<br />
String or binary data would be truncated in table 'tempdb.dbo.#A6AD698B', column 'somevalue'. Truncated value: '33333'.<br />
<br />
As you can see you also get the error, the table name is the internal table name for the table variable tied to your session<br />
<br />
<br />
What about Table Valued Parameters?<br />
<br />
<pre style="color: #333333; line-height: 16.25px;"><span style="color: #008800; font-weight: bold;">CREATE</span> <span style="color: #008800; font-weight: bold;">TYPE</span> TestTypeTrunc <span style="color: #008800; font-weight: bold;">AS</span> <span style="color: #008800; font-weight: bold;">TABLE</span>
( somevalue <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>),somevalue2 <span style="color: #007020;">varchar</span>(<span style="color: #0000dd; font-weight: bold;">5</span>));
<span style="color: #008800; font-weight: bold;">GO</span>
<span style="color: #008800; font-weight: bold;">DECLARE</span> @<span style="color: #008800; font-weight: bold;">table</span> TestTypeTrunc
<span style="color: #008800; font-weight: bold;">INSERT</span> @<span style="color: #008800; font-weight: bold;">table</span>
<span style="color: #008800; font-weight: bold;">SELECT</span> <span style="background-color: #fff0f0;">'555555555'</span>,<span style="background-color: #fff0f0;">'444444'</span></pre>
<br />
Here is the error for that <br />
<br />
Msg 2628, Level 16, State 1, Line 58<br />
String or binary data would be truncated in table 'tempdb.dbo.#AC6642E1', column 'somevalue'. Truncated value: '55555'.<br />
<br />
<br />
Pretty much the same message as for the table variable<br />
<br />
<br />
I do applaud Microsoft for finally fixing this.<br />
<br />
Here it is also in beautiful technicolor<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo456a8pVvcTFRau3Md0gDF85hjsjbwbd18PfcDbL44q_A7wUcoYnWk8p5lSi-dn0mSCE7rhOY_3msP4LC2PoPu5EPSIT98zRWsUMq_10O24v4ExX5u6OSZ1w9YiW99qu8AeDG/s1600/SQLTruncate.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="638" data-original-width="1195" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo456a8pVvcTFRau3Md0gDF85hjsjbwbd18PfcDbL44q_A7wUcoYnWk8p5lSi-dn0mSCE7rhOY_3msP4LC2PoPu5EPSIT98zRWsUMq_10O24v4ExX5u6OSZ1w9YiW99qu8AeDG/s640/SQLTruncate.PNG" width="640" /></a></div>
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com1