-- I end up using this one a lot. You can add it into a JOIN to filter out tables that are empty.
SELECT O.object_id
, SCHEMA_NAME(O.schema_id) [Schema]
, O.name [Table]
, SUM(P.Rows) [RowCount]
, O.modify_date
, O.create_date
FROM sys.objects O
JOIN sys.partitions P
ON O.object_id = P.object_id
WHERE O.type = 'U'
AND O.is_ms_shipped = 0x0
AND index_id < 2 -- 0:Heap, 1:Clustered
GROUP BY O.object_id, O.name, O.create_date, SCHEMA_NAME(O.schema_id)
, O.modify_date
HAVING SUM(P.Rows) > 0
-- For example:
DECLARE @VAR VARCHAR(100)
SET @VAR = 'Descp' -- replace the value between the single quotes with your search param
SELECT T.name [TABLE], C.name [Column], O.[RowCount]
FROM sys.tables T
JOIN sys.columns C
ON C.object_id = T.object_id
JOIN (
SELECT O.object_id
, O.name [Table]
, SUM(P.Rows) [RowCount]
, O.modify_date
, O.create_date
FROM sys.objects O
JOIN sys.partitions P
ON O.object_id = P.object_id
WHERE O.type = 'U'
AND O.is_ms_shipped = 0x0
AND index_id < 2
GROUP BY O.object_id, O.name, O.create_date, SCHEMA_NAME(O.schema_id), O.modify_date
HAVING SUM(P.Rows) > 0) O
ON O.object_id = T.object_id
WHERE C.name LIKE '%' + @VAR + '%'
Monday, July 2, 2018
Thursday, June 21, 2018
Delete Older Backup History from msdb Database
-- Gets the oldest backup date in the backupset table
SELECT MIN(backup_finish_date)
FROM msdb.dbo.backupset
-- Gets the newest backup date in the backupset table
SELECT MAX(backup_finish_date)
FROM msdb.dbo.backupset
-- Purges the backupset table of all records BEFORE the one below in quotes
USE msdb;
GO
EXEC sp_delete_backuphistory '6/1/18';
Friday, March 2, 2018
List all Stored Procedures on a SQL Server that get Executed
-- =============================================
-- Author: K Griffith
-- Create date: 09 Feb 2015
-- Description: Returns a listing of all SPs on the server that get used
-- Modify date: 02 Mar 2018
--=============================================
SELECT st.dbid [DB_ID]
, DB_NAME(st.dbid) [Database]
, OBJECT_SCHEMA_NAME(st.objectid,dbid) [Schema]
, OBJECT_NAME(st.objectid,dbid) [StoredProcedure]
, MAX(cp.usecounts) [ExecutionCount]
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
WHERE DB_NAME(st.dbid) IS NOT NULL
AND cp.objtype = 'proc'
AND st.dbid = 7
GROUP BY st.dbid
, DB_NAME(st.dbid)
, OBJECT_SCHEMA_NAME(objectid,st.dbid)
, OBJECT_NAME(objectid,st.dbid)
--, cp.plan_handle
ORDER BY [Database]
Friday, February 23, 2018
Splitting a Full Name Apart When It Has Been Stuffed into a Single Field
-- In case the need arises to split a comma-delimited name - for example, where the last and first name have been stuffed into the same field such as 'Lastname, Firstname'
SELECT [UserName]
, RTRIM(LTRIM(LEFT([FieldName], CHARINDEX(',', [FieldName]) -1))) [LastName]
, RTRIM(LTRIM(STUFF([FieldName], 1, CHARINDEX(',', [FieldName]), ''))) [FirstName]
FROM [DatabaseName].[dbo].[TableName]
Wednesday, July 9, 2014
Setting Up a New SQL Server 2008 R2 Cluster - Make SURE that the Cluster Object has Rights in Active Directory!
Being a DBA is something akin to being a duck-billed platypus: people try to classify you, but you really end up fitting into multiple categories. A DBA ends up doing lots of different things: writing SQL scripts, setting up jobs, restoring backups, and even some server administration.
At work, we normally have the vendor set up things like SQL Server clusters and we manage them after they are set up and running. For reasons unknown to me at the time, we had a vendor try and fail 3 times to set up a SQL Server cluster for us. The job then fell on me. I was a little apprehensive at first because LUNs, SAN space, etc are foreign concepts to me, but I said I would give it a try. I got really lucky. In his previous position, our network engineer was a server guy and had installed a SQL Server cluster from scratch - so I had some great wisdom and input from him. I was able to Google a great deal of what to do and, of course, I had our network engineer in the cube in front of me. Honestly, everything went seamlessly until I would get to the end of installing the first instance. It failed over and over again and we could not figure out why.
This may be something of a perfect storm because it involves Active Directory and AD here at my workplace may run differently than AD at your workplace, but I learned several things in this process. One is that when we are creating a SQL Server cluster, the cluster itself is an object in AD. What we finally found out was happening was that our newly created SQL cluster object needed to create other objects in our domain to complete the install and configuration, but it did not have the rights to do so in AD. You can be logged in as Domain Admin all day long and it will not make a difference unless the cluster object that you have created has the appropriate level of rights in AD. This one bit me good (and several times!) so I am making sure that I make note of it and underline it =)
At work, we normally have the vendor set up things like SQL Server clusters and we manage them after they are set up and running. For reasons unknown to me at the time, we had a vendor try and fail 3 times to set up a SQL Server cluster for us. The job then fell on me. I was a little apprehensive at first because LUNs, SAN space, etc are foreign concepts to me, but I said I would give it a try. I got really lucky. In his previous position, our network engineer was a server guy and had installed a SQL Server cluster from scratch - so I had some great wisdom and input from him. I was able to Google a great deal of what to do and, of course, I had our network engineer in the cube in front of me. Honestly, everything went seamlessly until I would get to the end of installing the first instance. It failed over and over again and we could not figure out why.
This may be something of a perfect storm because it involves Active Directory and AD here at my workplace may run differently than AD at your workplace, but I learned several things in this process. One is that when we are creating a SQL Server cluster, the cluster itself is an object in AD. What we finally found out was happening was that our newly created SQL cluster object needed to create other objects in our domain to complete the install and configuration, but it did not have the rights to do so in AD. You can be logged in as Domain Admin all day long and it will not make a difference unless the cluster object that you have created has the appropriate level of rights in AD. This one bit me good (and several times!) so I am making sure that I make note of it and underline it =)
Location:
Columbus, GA 31904, USA
Friday, October 4, 2013
Reboot Windows 2000, XP, and Vista from a Command Prompt
I came across a situation today where I needed to reboot an ancient XP workstation. However, since I was remoted into it, it did not give me that option in the start menu (at least, I am guessing that is why I did not see the option). At any rate, I was able to Google this and it was a great solution. Open up a command prompt. Type:
SHUTDOWN -r -t 01
Then press Enter. In a dozen years of working in technology, I never had occasion to do this. The great thing about technology is that I am always learning new things =)
SHUTDOWN -r -t 01
Then press Enter. In a dozen years of working in technology, I never had occasion to do this. The great thing about technology is that I am always learning new things =)
Labels:
Windows Server Administration
Location:
Columbus, GA 31904, USA
Monday, August 26, 2013
Querying the Default Trace File
It has always been a bit of a pain having to open up a SQL Server trace file with SQL Server Profiler and try to find the information I am seeking. It's true that the trace can be saved to a table and queried, but this method is SO EASY. It is also great for auditing if you do not have SQL Server 2008 R2 Enterprise installed (We run SQL Server 2008 R2 Standard here at work).
There are several ways to run this query. Here is one that I am currently using in production to track any configuration changes:
DECLARE @TRC_PATH VARCHAR(500)
SELECT @TRC_PATH = CONVERT(VARCHAR(500), value)
FROM fn_trace_getinfo(DEFAULT)
WHERE property = 2
SELECT TEXTData, HostName, ApplicationName, DatabaseName, LoginName, SPID, StartTime
, EventSequence
FROM fn_trace_gettable(@TRC_PATH,1) fn
WHERE TEXTData LIKE '%configure%'
AND SPID<>@@spid
ORDER BY StartTime DESC
Of course you can change things around to suit your own needs - different fields in the SELECT, change the conditions of the WHERE clause, etc.
FYI, I got this info from this great, great article available at mssqltips.com: http://www.mssqltips.com/sqlservertip/2364/capturing-and-alerting-on-sql-server-configuration-changes/
There are several ways to run this query. Here is one that I am currently using in production to track any configuration changes:
DECLARE @TRC_PATH VARCHAR(500)
SELECT @TRC_PATH = CONVERT(VARCHAR(500), value)
FROM fn_trace_getinfo(DEFAULT)
WHERE property = 2
SELECT TEXTData, HostName, ApplicationName, DatabaseName, LoginName, SPID, StartTime
, EventSequence
FROM fn_trace_gettable(@TRC_PATH,1) fn
WHERE TEXTData LIKE '%configure%'
AND SPID<>@@spid
ORDER BY StartTime DESC
Of course you can change things around to suit your own needs - different fields in the SELECT, change the conditions of the WHERE clause, etc.
FYI, I got this info from this great, great article available at mssqltips.com: http://www.mssqltips.com/sqlservertip/2364/capturing-and-alerting-on-sql-server-configuration-changes/
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31904, USA
Wednesday, August 14, 2013
Disable All Enabled Jobs and Re-enable Them
I recently came across a situation where I was working with a vendor that was upgrading one of our applications. He asked me to backup the production database and disable all jobs on the production SQL Server. I could just go through the SSMS GUI and do all of this, but I like to automate anything I can. It keeps me on my toes and (most of the time) makes it to where I don't have to be remoted in or at my desk if something needs to happen during off hours.
Simply disabling all of the jobs should be pretty easy, right? Jobs in SQL Server are stored in the msdb database in the sysjobs table. Since I want to disable all the jobs, I need to change the [enabled] tinyint field in the sysjobs table and change it to 0 (0 for disable, 1 for enable). Easy peasy:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 0
However, there is one small problem with this. I this particular situation, there are 15 jobs on this SQL Server and only 13 of them are enable. There are 2 disabled jobs on this server, but we do use those jobs from time to time, so I don't want to delete them. The jobs will need to be re-enabled when the vendor finishes the work, but if I simply run:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 1
that enables ALL of the jobs, including the 2 that need to stay disabled. So here is how I got around it. I decided to create a table and store the job_id (the unique identifier for the job in the sysjobs table) for each enabled job in it. I can use our good friend, the SELECT INTO statement, to create this table on the fly:
USE [msdb]
SELECT job_id
INTO enabled_jobs
FROM sysjobs
WHERE [enabled] = 1
So now I have a snapshot of the enabled jobs at a given point in time. I can then run an UPDATE statement and disable all of these jobs for the vendor:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 0
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
But there is just one more little problem: I want to automate this. Since I need to take my snapshot of which jobs are enabled at a point in time, I may need to create and recreate the enabled_jobs table over and over - especially if this code is to be reusable. So let's try this:
USE [msdb]
-- DROP TABLE if it already exists
IF OBJECT_ID (N'dbo.enabled_jobs') IS NOT NULL
DROP TABLE enabled_jobs
-- Get the job_id of all jobs that are currently enabled and create a new table
-- on the fly to hold those IDs
-- Store these job_ids in a table so that there is a record of the jobs that were
-- enabled and the ones that were not
SELECT job_id
INTO enabled_jobs
FROM sysjobs
WHERE [enabled] = 1
-- Disable all jobs that are enabled
UPDATE sysjobs
SET [enabled] = 0
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
Now I can put all of this in a stored procedure and reuse it. Since we do not drop the enabled_jobs table at the end of our statement, it still exists and I can use it later to re-enable these jobs when our vendor has completed the work. It will re-enabled the ones that were previously enabled and keep the ones that were disabled disabled:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 1
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
I hope you enjoyed this entry and that maybe it even saved you a little time or that you learned something.
Simply disabling all of the jobs should be pretty easy, right? Jobs in SQL Server are stored in the msdb database in the sysjobs table. Since I want to disable all the jobs, I need to change the [enabled] tinyint field in the sysjobs table and change it to 0 (0 for disable, 1 for enable). Easy peasy:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 0
However, there is one small problem with this. I this particular situation, there are 15 jobs on this SQL Server and only 13 of them are enable. There are 2 disabled jobs on this server, but we do use those jobs from time to time, so I don't want to delete them. The jobs will need to be re-enabled when the vendor finishes the work, but if I simply run:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 1
that enables ALL of the jobs, including the 2 that need to stay disabled. So here is how I got around it. I decided to create a table and store the job_id (the unique identifier for the job in the sysjobs table) for each enabled job in it. I can use our good friend, the SELECT INTO statement, to create this table on the fly:
USE [msdb]
SELECT job_id
INTO enabled_jobs
FROM sysjobs
WHERE [enabled] = 1
So now I have a snapshot of the enabled jobs at a given point in time. I can then run an UPDATE statement and disable all of these jobs for the vendor:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 0
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
But there is just one more little problem: I want to automate this. Since I need to take my snapshot of which jobs are enabled at a point in time, I may need to create and recreate the enabled_jobs table over and over - especially if this code is to be reusable. So let's try this:
USE [msdb]
-- DROP TABLE if it already exists
IF OBJECT_ID (N'dbo.enabled_jobs') IS NOT NULL
DROP TABLE enabled_jobs
-- Get the job_id of all jobs that are currently enabled and create a new table
-- on the fly to hold those IDs
-- Store these job_ids in a table so that there is a record of the jobs that were
-- enabled and the ones that were not
SELECT job_id
INTO enabled_jobs
FROM sysjobs
WHERE [enabled] = 1
-- Disable all jobs that are enabled
UPDATE sysjobs
SET [enabled] = 0
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
Now I can put all of this in a stored procedure and reuse it. Since we do not drop the enabled_jobs table at the end of our statement, it still exists and I can use it later to re-enable these jobs when our vendor has completed the work. It will re-enabled the ones that were previously enabled and keep the ones that were disabled disabled:
USE [msdb]
UPDATE sysjobs
SET [enabled] = 1
WHERE job_id IN
(SELECT job_id
FROM enabled_jobs)
I hope you enjoyed this entry and that maybe it even saved you a little time or that you learned something.
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31904, USA
Wednesday, July 31, 2013
Changing the Restrict Access Option in SQL Server
Ever get something like this annoying popup when you try to change a SQL Server database from SINGLE_USER to MULTI_USER?
This is what always happens to me when a database is already locked down into SINGLE_USER mode and I try to change the property in the GUI. In order to change it, I run this T-SQL in SSMS (SQL Server Management Studio):
ALTER DATABASE [MyDatabase]
SET MULTI_USER WITH ROLLBACK IMMEDIATE;
If there is already an operation going on in the database, the "WITH ROLLBACK IMMEDIATE" will take things back to their previous state before the transaction started. After the statement completes, more than one authorized user should be able to access the database. Always use caution when performing any ALTER DATABASE statement on a production server. When a database is locked down in SINGLE_USER mode, an icon of a person will appear next to the database in SSMS:
ALTER DATABASE [MyDatabase]
SET MULTI_USER WITH ROLLBACK IMMEDIATE;
If there is already an operation going on in the database, the "WITH ROLLBACK IMMEDIATE" will take things back to their previous state before the transaction started. After the statement completes, more than one authorized user should be able to access the database. Always use caution when performing any ALTER DATABASE statement on a production server. When a database is locked down in SINGLE_USER mode, an icon of a person will appear next to the database in SSMS:
If you refresh your view of the databases in object explorer after running the above T-SQL, the person icon should disappear from the database indication that it is in MULTI_USER mode.
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31904, USA
Wednesday, November 14, 2012
The DATALENGTH() Function
Yesterday I was getting a very interesting error in SSRS. A user was trying to export data to Excel and it was basically telling her that it was too much data to fit into Excel. I began to suspect that one of the fields in the report was quite large. I went to run a standard T-SQL query to see exactly how large the field in question was. The field was named [Description] and it's type was text:
USE [MyDatabase]
SELECT LEN([Description])
FROM MyTable
Of course, you know what happened:
Msg 8116, Level 16, State 1, Line 3
Argument data type text is invalid for argument 1 of len function.
So, the LEN() function cannot be used on text type fields. Was there a LEN() equivalent for the text type? A little googling revealed that there was:
DATALENGTH()
This function was exactly what I needed to get the length for a text type field.
USE [MyDatabase]
SELECT LEN([Description])
FROM MyTable
Of course, you know what happened:
Msg 8116, Level 16, State 1, Line 3
Argument data type text is invalid for argument 1 of len function.
So, the LEN() function cannot be used on text type fields. Was there a LEN() equivalent for the text type? A little googling revealed that there was:
DATALENGTH()
This function was exactly what I needed to get the length for a text type field.
Monday, October 1, 2012
Finding the Name of the Primary Domain Controller
1. Open a command prompt
2. Type echo %logonserver%
That's it - not very complicated at all. The output in the command prompt is that machine's PDC (Primary Domain Controller).
2. Type echo %logonserver%
That's it - not very complicated at all. The output in the command prompt is that machine's PDC (Primary Domain Controller).
Labels:
Windows Server Administration
Location:
Columbus, GA 31904, USA
Monday, July 30, 2012
Rebuilding Indexes with T-SQL
In my last position, I ended up writing a lot of T-SQL. I have recently taken on a new position and I am the company's sole DBA, so there is less T-SQL, but it certainly has not gone away completely. Case in point, SQL Server's maintenance plans are pretty cool and very simple to implement, but they are not bullet proof. Last week I kept getting an alert an index rebuild job had failed. I took a look at the maintenance plan, troubleshot it, and even rebuilt it but it continued to fail. I then decided to look at the underlying T-SQL associated w/ this job. It was failing on one particular index rebuild and succeeding on the rest of them. However, this still shows up in the job as a failure. I decided to script out the index rebuild and since then I have had no issues with the job. I opted to leave the CATCH block empty. Depending on how important the job is, it may be wise to have something in the CATCH that writes to a table so that one can be aware of exactly which index rebuilds failed.Additionally, I opted to sort in the tempdb as opposed to the DB itself. Once again, that one is your call. It will depend on how your environment is set up as to whether or not this is a good idea.
USE [DB_NAME_GOES_HERE]
DECLARE @SQL VARCHAR(3000)
, @START INT
, @LAST INT
, @TABLE_NAME VARCHAR(200)
, @IX_NAME VARCHAR(200)
CREATE TABLE #TEMP(ID INT IDENTITY(1,1), [TABLE_NAME] VARCHAR(200)
, [IX_NAME] VARCHAR(200))
INSERT #TEMP
SELECT '[' + S.NAME + '].[' + T.NAME + ']' AS [TABLE_NAME], I.NAME AS [IX_NAME]
FROM SYS.INDEXES I
INNER JOIN sys.tables T
ON I.object_id = T.object_id
INNER JOIN sys.schemas S
ON T.schema_id = S.schema_id
WHERE I.INDEX_ID > 0
ORDER BY T.NAME, I.NAME
SET @START = (SELECT MIN(ID) FROM #TEMP)
SET @LAST = (SELECT MAX(ID) FROM #TEMP)
WHILE @START <= @LAST
BEGIN
SET @TABLE_NAME = (SELECT [TABLE_NAME] FROM #TEMP WHERE ID = @START)
SET @IX_NAME = (SELECT [IX_NAME] FROM #TEMP WHERE ID = @START)
SET @SQL = ' BEGIN TRY
ALTER INDEX [' + @IX_NAME + '] ON ' + @TABLE_NAME + '
REBUILD WITH ( PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON, ONLINE = OFF
, SORT_IN_TEMPDB = ON )
END TRY
BEGIN CATCH ' +
-- If you want something to happen in the Catch block
-- , place that code here
' END CATCH'
EXEC (@SQL)
SET @START = @START + 1
END
DROP TABLE #TEMP
USE [DB_NAME_GOES_HERE]
DECLARE @SQL VARCHAR(3000)
, @START INT
, @LAST INT
, @TABLE_NAME VARCHAR(200)
, @IX_NAME VARCHAR(200)
CREATE TABLE #TEMP(ID INT IDENTITY(1,1), [TABLE_NAME] VARCHAR(200)
, [IX_NAME] VARCHAR(200))
INSERT #TEMP
SELECT '[' + S.NAME + '].[' + T.NAME + ']' AS [TABLE_NAME], I.NAME AS [IX_NAME]
FROM SYS.INDEXES I
INNER JOIN sys.tables T
ON I.object_id = T.object_id
INNER JOIN sys.schemas S
ON T.schema_id = S.schema_id
WHERE I.INDEX_ID > 0
ORDER BY T.NAME, I.NAME
SET @START = (SELECT MIN(ID) FROM #TEMP)
SET @LAST = (SELECT MAX(ID) FROM #TEMP)
WHILE @START <= @LAST
BEGIN
SET @TABLE_NAME = (SELECT [TABLE_NAME] FROM #TEMP WHERE ID = @START)
SET @IX_NAME = (SELECT [IX_NAME] FROM #TEMP WHERE ID = @START)
SET @SQL = ' BEGIN TRY
ALTER INDEX [' + @IX_NAME + '] ON ' + @TABLE_NAME + '
REBUILD WITH ( PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON, ONLINE = OFF
, SORT_IN_TEMPDB = ON )
END TRY
BEGIN CATCH ' +
-- If you want something to happen in the Catch block
-- , place that code here
' END CATCH'
EXEC (@SQL)
SET @START = @START + 1
END
DROP TABLE #TEMP
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31904, USA
Tuesday, July 10, 2012
Great Quote of the Day
This concept is simple and primary, but often overlooked:
"...it is a good idea to create non-clustered indexes on all foreign keys. You will always run lots of queries, and also use the JOIN operator, based on your primary and foreign keys."
- Wagner Crivelini
From the article SQL and the JOIN Operator
"...it is a good idea to create non-clustered indexes on all foreign keys. You will always run lots of queries, and also use the JOIN operator, based on your primary and foreign keys."
- Wagner Crivelini
From the article SQL and the JOIN Operator
Location:
Columbus, GA 31909, USA
Friday, May 25, 2012
Converting a Julian Date
I had to accomplish this at work yesterday. I did not see anything in the pre-defined SQL Server functions that would do it, so I started Googleing. Thank goodness for stackoverflow.com.
DECLARE @JULIAN_DATE INT = 2012146
SELECT DATEADD(D, CAST(SUBSTRING(
CAST(@JULIAN_DATE AS VARCHAR), 5, LEN(@JULIAN_DATE) - 4) AS INT) - 1,
CAST('1/1/' + SUBSTRING(CAST(@JULIAN_DATE AS VARCHAR),1,4) AS DATE))
AS [NEW DATE]
http://stackoverflow.com/questions/2692361/most-concise-way-to-convert-julian-date-yyyyday-of-year-to-sql-datetime
This T-SQL is a little too verbose to be writing over and over again so later today I'm going to roll it up into a UDF (User Defined Function).
DECLARE @JULIAN_DATE INT = 2012146
SELECT DATEADD(D, CAST(SUBSTRING(
CAST(@JULIAN_DATE AS VARCHAR), 5, LEN(@JULIAN_DATE) - 4) AS INT) - 1,
CAST('1/1/' + SUBSTRING(CAST(@JULIAN_DATE AS VARCHAR),1,4) AS DATE))
AS [NEW DATE]
http://stackoverflow.com/questions/2692361/most-concise-way-to-convert-julian-date-yyyyday-of-year-to-sql-datetime
This T-SQL is a little too verbose to be writing over and over again so later today I'm going to roll it up into a UDF (User Defined Function).
Labels:
T-SQL
Sunday, May 20, 2012
Modifying Data Through a View
The following requirements MUST be met to modify data through a view in SQL Server:
- The modification can reference exactly ONE table
- Columns in the view must reference columns in a table directly
- The column cannot be derived from an aggregate
- The column cannot be computed as the result of a UNION/UNION ALL, INTERSECT, EXCEPT, or CROSSJOIN
- The column being modified cannot be affected by the DISTINCT, GROUP BY, or HAVING clause
- The TOP operator cannot be used
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31909, USA
Monday, April 23, 2012
NOT, AND, OR: the Boolean Operators in T-SQL
The boolean operators in T-SQL are NOT, AND, and OR and are executed in a SQL statement in that order.
- The NOT operator generally hurts query performance because indexes cannot be used for a WHERE clause when the NOT operator is used *
- Indexes can be used when the OR operator is specified, but all columns referenced by the OR must be included in an index or none of the indexes are used
- Performance is often improved when the AND operator is used because the AND operator generally results in a smaller result set
SELECT FirstName, LastName FROM [Users].[dbo].[Employees] WHERE LastName LIKE '*ones'
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31909, USA
Sunday, April 22, 2012
Get the Number of Rows from Each Table in a Database
In order to see how many rows a particular table in a database has in SQL Server, you can simply right click on the table and select properties. It will be in available in one of the sections. However, what if you need to see how many rows every table in the database has at the same time? I find this query works well for me in those cases:
SELECT T.NAME, S.ROWS
FROM SYSINDEXES S
INNER JOIN SYS.TABLES T
ON T.OBJECT_ID = S.ID
WHERE S.INDID > 2
ORDER BY S.ROWS DESC
SELECT T.NAME, S.ROWS
FROM SYSINDEXES S
INNER JOIN SYS.TABLES T
ON T.OBJECT_ID = S.ID
WHERE S.INDID > 2
ORDER BY S.ROWS DESC
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31909, USA
Thursday, April 19, 2012
SQL Server Times Out When Adding a New Column to a Table
Recently at work, I needed to add an auto-incremented int field to a table that had 2.5 million records and was about 50 columns wide. Not a terribly large table to some folks, but our server is not the most robust. So every time I tried to do this in the UI in SSMS, it would process for a while and then time out and tell me something to the effect that the changes could not be save to the table. I then got the bright idea just to try this as a query:
ALTER TABLE [database].[dbo].[tableName]
ADD ID INT IDENTITY(1,1) NOT NULL
It processed in something like 2 second and worked like a charm. Weird that it should fail in the UI, but work as a script. I will keep this in mind. Also, it NEVER hurts to be able to write the T-SQL by hand to accomplish a task.
ALTER TABLE [database].[dbo].[tableName]
ADD ID INT IDENTITY(1,1) NOT NULL
It processed in something like 2 second and worked like a charm. Weird that it should fail in the UI, but work as a script. I will keep this in mind. Also, it NEVER hurts to be able to write the T-SQL by hand to accomplish a task.
Labels:
SQL Server Administration,
T-SQL
Location:
Columbus, GA 31909, USA
Tuesday, September 13, 2011
IIS 7 401 Error - Unauthorized: Access is denied due to invalid credentials
I thought this one was going to drive me crazy. I set up a web application on a Windows Server 2008 using IIS 7 and ASP.NET 4. I set it up to use Window Authentication but I just kept getting a 401 error - which made no sense. Everything on the network was windows-based. There should have been no problem finding my credentials. I was finally lucky enough to come across this on the web:
http://social.technet.microsoft.com/Forums/en-US/winserversecurity/thread/c9239a89-fbee-4adc-b72f-7a6a9648331f/Below are the steps to stop this from happening:
- Open IIS and select the website that is causing the 401
- Open the "Authentication" property under the "IIS" header
- Click the "Windows Authentication" item and click "Providers"
- The issue should be that Negotiate is above NTLM. Move the NTLM to the top spot and that should fix it.
Sunday, August 21, 2011
REPLACE() VS RTRIM() and LTRIM()
I recently had a VERY interesting experience while cleaning up some data. I had about 8GB of SQL Server table data - all nvarchar(max) stuff. The tables needed to be compared to find the differences so the data really did need to be cleaned up. For a while I used an UPDATE statement that contained the REPLACE() function in it. It worked well, but took over an hour to complete. I began to think that there HAD to be a better way to do this. All I was really concerned about was trimming white space off the front and end of the field. I thought I would try a combination of the RTRIM() and LTRIM() functions just to see what would happen like so:
This one simple change shaved 40 minutes off my job! Why? Because REPLACE() has to crawl across each field character by character to find each what needs to be replaced. The TRIM functions are only concerned about white space at the beginning and end of the field and so, in this case, they are much faster. There is nothing quite like using the right tool for the job. Many thanks to a very wise DBA for explaining what was going on.
UPDATE table
SET field1 = LTRIM(RTRIM(field1))
This one simple change shaved 40 minutes off my job! Why? Because REPLACE() has to crawl across each field character by character to find each what needs to be replaced. The TRIM functions are only concerned about white space at the beginning and end of the field and so, in this case, they are much faster. There is nothing quite like using the right tool for the job. Many thanks to a very wise DBA for explaining what was going on.
Subscribe to:
Posts (Atom)

