Remote Desktop won’t go back to Full Screen after Mnimization in Windows 7

By Rudy June 29th, 2010, under Windows

So, last month I finally got my new work system. It is a nice Dell Precision M4500 running an Intel Core i5, 8GB RAM, tons of Hard Drive space, etc. I also made the move to Windows 7 X64 from Windows Vista. In reality, I don’t use many of the super advanced OS features. I wants the OS to “stay out of the way” of my day to day tasks. One of those tasks is remoting into servers and headless desktops. It is not that unusual for me to have several Remote Desktop(MSTSC.exe) windows open at the same time.

Now, I will usually fire up the remote desktop windows in fullscreen mode and take care of some tasks. Once complete, I will minimize the window, like any other window. The problem appears when I restore the Remote Desktop window. Instead of returning to true fullscreen, I find that the Windows 7 Taskbar, or Superbar, blocked the window from returning to full screen. Also, the remote desktop window now has scroll bars.

Luckily, the fix is pretty easy. We all know we can use Ctrl-Alt-End to send a Ctrl-Alt-Del  message to the remote desktop. Similarly, we can use Ctrl-Alt-Break to force the Remote Desktop window to a true full screen. Superbar or not, the Remote Desktop is now full screen again!

Post to Twitter

Using Windows Media Center on a Dual Screen Setup with Windows 7 x64

By Rudy June 25th, 2010, under Windows

If your PC came with Windows 7, chances are you already have Windows Media Center installed. Some PCs come with a built in TV tuner, or you can get an external TV tuner at a reasonable price at your favorite store. One of the neat things about having a TV tuner on your machine is is having the ability to watch live or recorded TV right on your machine via Windows Media Center. Of course, when you’re working on something else, you’re going to have to cover the TV image. Of course, when you have a multi monitor setup, you can have your favorite application running full screen on one monitor and all your work applications on another monitor. However, I have noticed an annoying issue on Windows 7 x64.
It seems that running Windows Media Center on full screen mode also freezes the mouse on the same monitor. Meaning, after you maximize, you cannot move the mouse off of the monitor running Windows Media Center. Not ideal, if you want to work on other things on your primary monitor. I searched around the web to see if there is a patch or hotfix for the issue. I didn’t really find anything, except for a work around from Microsoft.
The work around is pretty simple:

  1. Open Windows Media Center on your secondary monitor
  2. Maximize Windows Center
    1. The mouse is now stuck on the secondary monitor
  3. Hit the Windows key on your keyboard
  4. Move the mouse freely again!

Perhaps the next Windows 7 service pack will have something for this issue.

Post to Twitter

Querying an Oracle linked server fails

By Rudy June 8th, 2010, under Programming, SQL

The other day, I needed to pull some data from an Oracle server on our network. The oracle server was set up as a linked server on my SQL Server 2005 machine. For some reason, the query didn’t work. Now, when working with an oracle linked server, you have to include the linked server name, the schema name and the table name. Also, you can use an alias just like any SQL Server table. But, the key thing is to include the schema and table name. The query looks something like this:

select col1
from [OracleServer]..[schema_name].[table_name]

For some reason, the query failed with this error:

Msg 7314, Level 16, State 1, Line 1
The OLE DB provider "MSDAORA" for linked server "OracleServer" does not contain the table ""schema_name"."table_name"". The table either does not exist or the current user does not have permissions on that table.

Now, I could query the data using Toad or MS Access, so I knew the data was OK. There must be another issue that is causing my query to fail. I did some digging around and found the following KB from Microsoft:

Can’t Use Four-Part Name to Query Oracle Table If Name Contains Lowercase Characters You read that correctly; If you use lower case characters in your table name, the query fails. The fix is pretty easy, just modify you query to use upper case letters only:

select col1
from [ORACLERSERVER]..[SCHEMA_NAME].[TABLE_NAME]

And just like that, the query works! I know the KB says the issue exists on SQL Server 2000, but I am seeing the issue on SQL Server 2005 as well. Good luck!

Post to Twitter

Great Circles in SQL Server 2005 and SQL Server 2000

By Rudy May 14th, 2010, under SQL

Recently, I had a request to calculate the distance between 2 GPS coordinates. Now, the system I am working with is SQL Server 2005. SQL Server 2008 gives us the geography data type, which is great and has a lot of powerful features. But, if you’re using SQL Server 2000 or 2005, you won’t have access to any spatial data types.
Now, the table i was working with had the city name along with the Latitude and Longitude information. So, I went over to wikipedia and got the formula for calculating distance using great circles. I won’t go into the details of converting the formula to SQL, but the conversion is pretty straightforward.  Check out the script below:

/*
* Function fn_Distance_Calculator
* The function fn_Distance_Calculator calculates the distance between 2 GPS coordinates
* Uses the formula from Wikipedia:
* http://en.wikipedia.org/wiki/Great-circle_distance
*
* Rudy Rodarte 2004 Original version
* 2010-05-14 Converted the code to a function.
*/
ALTER function [dbo].[fn_Distance_Calculator] (
/* Declare Parameters */
@latitudeA float
/* The latitude of the first point */
,@longitudeA float
/* The longitude of the first point */
,@latitudeB float
/* The latitude of the second point */
,@longitudeB float
/* The longitude of the second point */
)
RETURNS FLOAT
AS
BEGIN

-- Declare the variable which will hold
-- the distance

DECLARE @Distance float


-- Declare the Radian versions of the coordinates
DECLARE @latA float
,@lonA float
,@latB float
,@lonB float


-- Convert the degrees to radians.
select @latA = radians(@latitudeA )
select @lonA = radians(@longitudeA)

select @latB = radians(@latitudeB)
select @lonB = radians(@longitudeB)


-- Execute the calculation
select @distance =
atan(
sqrt(
power(
( cos(@latB) * sin( @lonB-@lonA) )
,2) +
power(
( cos(@latA) * sin(@latB) )
-
( sin(@latA)*cos(@latB)* cos( @lonB-@lonA) )
,2)
)
/
(
( sin(@latA) * sin(@latB) )
+
( cos(@latA) * cos(@latB) * cos( @lonB-@lonA) )
)
) * 6372.795 -- Earth's circumfrence in miles

-- Return the number
RETURN @Distance

END

With the coordinates for two cities in hand, the function will give you the distance “as the crow flies.” The function will give you the great circle distance between two points, even if there may be a shorter, more direct route between the two points.

Post to Twitter

Automatic Index Rebuilding

By Rudy April 23rd, 2010, under SQL

While working on a large project, I found that the queries were running slower and slower as the days went on. We were working with current and historical data and were only joining about 3-5 tables at a time. Each join was bringing back between only about 50K rows or so, and the results were aggregated and tossed up on an SSRS page. Since things were going well at first and started slowing down over time, I figured the indices were probably the cause.

Fragmented Index

Fragmented Index

If you don’t know much about indices, or you need to brush up on your knowledge, check out this article from simple-talk.com. You will learn all about the B-Tree structure .
So I looked at some of the tables just using the properties window and found that there was some index fragmentation going on. The rule of thumb that I have read in multiple places is 30% fragmentation and around 90% page fullness. [citation needed] Here is one of the smaller tables with over 80% fragmentation.

Now, I wanted to clean up all of these fragmented indices. One way to rebuild the indices is via T-SQL. You could use a query like this one to rebuild your index:

ALTER INDEX [TableName] ON [dbo].[TableName] REBUILD WITH (FILLFACTOR = 90)

But I didn’t want to use this T-SQL script and manually replace the table and index name for each and every index. I knew that I would have to use stuff like sys.dm_db_index_physical_stats, sys.dm_db_index_usage_stats, or sys.objects to build out a script where I could loop through and get the table and index name and toss them into the T-SQL script. I looked around the web and found GOLD on sqlserverpedia.com!

Index Maintenance via sqlserverpedia.com

This script is really powerful and has several great options. You can print out and see what indices are targets for rebuilding, without actually touching them. You can target a specific table, or all of the tables in a database. In fact, I recommend you read the script carefully to familiarize yourself with all the options. Now, I won’t reproduce the script here, but I will show you the usage I have set up for this script.

Exec dbo.dba_indexDefrag_sp
@executeSQL = 1
, @minFragmentation = 80
, @database = 'DB_Name'

Just schedule this as an SQL Job or inside of a DTS or SSIS package to run every day/week/month, etc. You’ll find that your queries run faster as your indices stay healthy.

Here is a quick look at the index after running the script. The index on this table is defragmented, the index uses less pages and the pages are full. As a bonus, all of the indices on the table are defragmented.

Defragmented Index

Defragmented Index

Post to Twitter

Unshare Folders in Windows 7

By Rudy April 22nd, 2010, under Windows

I was formatting the several of my machines the other day and I was moving files back and forth. Sure, for MP3s or videos, I use an external USB hard drive. But there are smaller files, such as the Adobe Flash installer or Opera, which are pretty small. For those smaller files, I use a drop folder. The drop folder is simply a folder where I grant read/write permissions to everyone. That way, people can drop files there for me. Or I have files sitting out there for, destined for another PC. Now, I made the move to Windows 7, so I had to relearn a few things. Once I was done moving files around, I wanted to unshare the drop folders. However, the share dialog looks different from the old Windows 7 versus Vista and XP. What to do, what to do. Well, instead of right-clicking and going to properties, you simply right-click and point to Share with and select “Nobody.” Voila, the share is gone!

Post to Twitter

Kill all Connections to a Database in SQL Server

By Rudy March 23rd, 2010, under SQL

One of the databases I work with runs a ton of updates overnight and in the early morning. Now, from time to time I run into a problem where a user has a lock on a table. This usually stems from, as far as I can tell, an MS Access query that is left open on their machines. Since the access query has a lock, I cannot refresh or merge anything into those tables until the user releases the lock. Bad news for anyone wanting fresh data first thing in the morning. What I found as a bit of a nuclear option, but it works great in this situation: Just kill all of the connections to the DB! Here is the script that I found on iMIS Community.

-- Usage sp_KillSpidsByDBName MyDBName
CREATE PROCEDURE [dbo].[sp_KillSpidsByDBName]
	@dbname sysname = ''
AS
BEGIN

-- check the input database name
IF DATALENGTH(@dbname) = 0 OR LOWER(@dbname) = 'master' OR LOWER(@dbname) = 'msdb'
	RETURN

DECLARE @sql VARCHAR(30)
DECLARE @rowCtr INT
DECLARE @killStmts TABLE (stmt VARCHAR(30))

-- find all the SPIDs for the requested db, and create KILL statements
--   for each of them in the @killStmts table variable
INSERT INTO @killStmts SELECT 'KILL ' + CONVERT(VARCHAR(25), spid)
	FROM master..sysprocesses pr
	INNER JOIN master..sysdatabases db
	ON pr.dbid = db.dbid
	WHERE db.name = @dbname

-- iterate through all the rows in @killStmts, executing each statement
SELECT @rowCtr = COUNT(1) FROM @killStmts
WHILE (@rowCtr > 0)
	BEGIN
		SELECT TOP(1) @sql = stmt FROM @killStmts
		EXEC (@sql)
		DELETE @killStmts WHERE stmt = @sql
		SELECT @rowCtr = COUNT(1) FROM @killStmts
	END

END

GO

I simply execute this stored procedure from ANOTHER DATABASE before running the updates. This also works when trying to perform a full restore on a database that people are still pinging for one reason or another. I would not recommend this for use on databases where users are reading and writing. But for reporting only type databases, this should be OK. But use your best judgement!

Post to Twitter

Importing Data into SQL Server – Using Excel Shortcuts

By Rudy March 17th, 2010, under SQL

I’ll be the first to say, the switch from DTS to SSIS was painful. DTS would go through a lot of implicit conversions so you didn’t have to worry or think about them. But SSIS was not as merciful. From different fields lengths to different encodings, SSIS wants you to be specific. Sometimes, it is just quicker to use some excel trickery than figuring out that you should have defined a column as a String 65 instead of the default String 50.

We will use the CountryList.csv file and CountryList table from the original Importing Data in SQL Server post. When we open up the file in Excel, we have a lot of built in functions at our disposal. The function that interests me most is the CONCATENATE function.

Now, the strategy here is to :

  1. Build the key portions of the INSERT string once
  2. Use the data in the current row to build an INSERT statement
  3. Use the fill handle (the small black square in the lower right side of a cell) to create the remaining INSERT statements.

Now, I will refer to explicit cells in the file, so it is important that you follow along. However when using this on your own, you will substitute the Cell references as needed.

Navigate to cell O2 in the CountryList.csv file. Type in the following text:

INSERT INTO CountryList(CountryName,CountryCode2,CountryCode3) VALUES ('

As you can see, we have the INSERT keyword, the table name, the VALUES keyword and the first apostrophe.  This creates slot for the countryName column. Navigate to cell P2 and cell Q2 and insert the following text:

'','

Don’t be fooled. Those are two apostrophes, not a quotation mark. The reason we have to use 2 apostrophes is because a leading apostrophe tells Excel to treat anything after the apostrophe as a string. This is useful when you’re dealing with data that may contain a leading zero, such as a zip code. As you can see, we have the double apostrophe, which will translate into one apostrophe, a comma, to separate the two fields, and another apostrophe, which starts out the next field. These will be used as the divisions between the CountryName, countryCode2 and CountryCode3.

Next, Navigate to Cell R2 and add the following text:

'')

Once again, we see the double apostrophe, which translates into a single apostrophe and the closed parenthesis. This string will close off the CountryCode3 column as well as close the insert statement. Now, we will see the power of the CONCATENATE statement.

Navigate to the column S2. From there you will type the following command:

=CONCATENATE(O2,B2,P2,K2,Q2,L2,R2)

You will see this text in the Formula bar above the current sheet. Lets take a closer look at this string. B2 represents the CountryName, K2 represents the 2 digit Country Code and L2 represents the 3 Digit country code name. O2 is the INSERT command string, P2 and Q2 are the apostrophe, comma, apostrophe strings and R2 is the apostrophe, closed parenthesis string. It looks a little confusing, however, when you hit enter, Cell S2 will now contain the following text:

INSERT INTO CountryList(CountryName,CountryCode2,CountryCode3) VALUES ('Afghanistan','AF','AFG')

Which is exactly what we wanted. Now, for the final step: creating the INSERT statement for all of the records in the file. Instead of copy and paste, simply highlight Cells O2 to S2. You will see a small black dot appear in the lower right side of the highlighted cells. This is called the Fill Handle.

All you need to do is double click the Fill Handle and the formula and text will self-replicate until the end of the file!

All that is left to do is copy everything from the S Column and paste the results into SQL Management Studio and execute the commands. All this takes about 2 minutes to do. Try it out!

Post to Twitter

Importing Data into SQL Server – Using the INSERT statement

By Rudy March 16th, 2010, under SQL

Sometimes, the easiest and quickest way to get data into SQL Server is to simply use an INSERT statement.  Here is what the INSERT statement looks like in Books Online(BOL)

[ WITH <common_table_expression> [ ,...n ] ]
INSERT
    [ TOP ( expression ) [ PERCENT ] ]
    [ INTO ]
    { <object> | rowset_function_limited
      [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
    }
{
    [ ( column_list ) ]
    [ <OUTPUT Clause> ]
    { VALUES ( ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ] )
    | derived_table
    | execute_statement
    | <dml_table_source>
    | DEFAULT VALUES
    }
}
[; ]

<object> ::=
{
    [ server_name . database_name . schema_name .
      | database_name .[ schema_name ] .
      | schema_name .
    ]
        table_or_view_name
}

<dml_table_source> ::=
    SELECT <select_list>
    FROM ( <dml_statement_with_output_clause> )
                      [AS] table_alias [ ( column_alias [ ,...n ] ) ]
        [ WHERE <search_condition> ]
    [ OPTION ( <query_hint> [ ,...n ] ) ]

Ok, let stick to the basic and learn some quick insert techniques that you can use today. Recall that we are using the CountryList table, which we created in earlier examples. Here is the script to create the table:

CREATE TABLE dbo.CountryList
(
	CountryID	int	IDENTITY(1,1)
	,CountryName	varchar(50)	NOT NULL
	,CountryCode2	char(2)	NOT NULL
	,CountryCode3	char(3)	NOT NULL
	,lastUpdated	smalldatetime NOT NULL default getdate()
)

The easiest INSERT statement goes something like this:

INSERT INTO TABLENAME(Col1,Col2,...,Colx) VALUES ('Val1','Val2',...,'Valx')

Here is a sample using the CountryList table:

INSERT INTO CountryList(CountryName,CountryCode2,CountryCode3)
VALUES
('Atlantis','AT','ATL')

Recall that the country table has an IDENTITY Column, so we cannot specifiy a value for the CountryID*. Also, the lastUpdate column has a default value, so we do not have to specify a value for that column, either. Lastly, we are enumerating the columns, so we will use the VALUES keyword.

Another technique is inserting data from one table into a new table by using the INTO keyword. INTO will take the results from a query, including column names and column types, and insert the results into a new table.

SELECT	*
INTO	CountryList2
FROM	countrylist
WHERE	countryName like 'M%';

In this sample, we are selecting every row where the country name starts with an M and inserting those rows into the table CountryList2, which does not exist at runtime. Notice, that we do not have to use the VALUES keyword. What we end up with is a table with the same column names, column types and the IDENTITY column on the CountryID. However, the lastUpdated column will not have the default value specified in the CREATE statement of CountryList table. Also, note that you cannot use the INTO keyword if the table already exists.

Next, we can use the SELECT and INSERT statement to move data from one table to another. We will use the CountryList table as a source and the CountryList2 table that we just created, as a destination.

INSERT INTO CountryList2(CountryName,CountryCode2,CountryCode3,lastUpdated)
SELECT	CountryName,CountryCode2,CountryCode3,GETDATE()
FROM	countrylist
WHERE	countryName like 'A%';

Notice here, that we had to specify a value for the lastUpdated column. This is because the lastUpdated column in the CountryList2 does not have a default value specified. However, the column retains the NOT NULL from the original CountryList table.

* Actually, you can specify a value for IDENTITY Columns. You need to enable IDENTITY_INSERT.

Post to Twitter

Importing Data into SQL Server – Using the Import Export Wizard

By Rudy March 15th, 2010, under SQL

Today begins the series on importing data into SQL Server 2005/2008 using the various built in tools. With SQL Server, there are several ways of getting your data from one place to another. Today, we will focus on using the wizard from SQL Server Management Studio. Before we begin, I am using a simple database called testdb. I am also using a country code file found at http://www.andrewpatton.com/countrylist.html. The file contains the 2 and 3 character ISO 3166 Country Code abbreviations, which we will use in our sample.

CountryList

The CSV file as seen in Excel 2007

Here is the script for the table that I will use in these samples.

create table dbo.countrylist
(
	CountryID		int	IDENTITY(1,1)
	,CountryName	varchar(50)	NOT NULL
	,CountryCode2	char(2)	NOT NULL
	,CountryCode3	char(3)	NOT NULL
	,lastUpdated	smalldatetime NOT NULL default getdate()
)

As you can see, the sample table does not include all of the columns from the sample file. In this example, we will only focus on the required columns. Though, you will soon see that the other columns matter, as well.

First thing, open up SQL Server Management Studio. From there, right click on the target database. Note, you are right clicking on the target table, but the entire database. From there, point to Tasks then Import Data.

You may get a Wizard introduction page. You can safely click next, if you do see the introduction page. From there, you will get a screen prompting you to select a datasource. Find the Flat File source in the Dropdown box.

From there, you will use Windows Explorer to navigate to the sample file. Ensure that you have selected CSV as the filetype, instead of TXT, since the sample file is a CSV file.

After selecting the file, ensure that you have Column Names in the First Data Row checked. This means that the file contains the column names. If this is unchecked, SQL Server will try and import the header row into the database, which is not desired. In this sample, we will also give a Text Qualifier of ” because some of the names are wrapped in quotation marks.

Next, you will inspect the file columns in the Columns section of the Data Source page. SQL Server let’s you review the first 100 columns.

View the columns and data in the file.

After reviewing the columns, you will examine the more advanced options. This is key because in this sample, we have a few items to take care of before importing the file. We see that, by default, SQL Server has assigned strings a length of 50.

Some of the columns in the file are larger that 50. Now, rather than going through and finding out what columns have what length, we will let SQL Server inspect the file by using the Suggest Types button.

Suggest Types

By Default, SQL Server will examine the first 100 rows and then give suggested types for each column. Since this file is rather small, we will examine the whole file. We find that the Capital column went out to over 60 characters!*

We will then examine the columns one last time using the Preview section of the Data Source page.

Once we are satisifed with the import preview, we will select the destination database.

From here, we will select the destination table. As you since the file and destination table are named the same, we do not have to take any action; The desired table is already selected for us. However, if the table did not exist, we have the option to create the table. We can also select a different table in the database. All we have to do is click on the destination column to select the desired table.

Since our table uses column names that differ from the column names in the file, we have to edit the source and destination mappings to ensure the data goes in the correct location.

In this example, the ID column and the lastUpdated column are automatically generated, so we will not worry about those. We will, however, map the country name, the ISO 2 and ISO 3 abbreviations. We will also ignore the remaining columns. We will then click OK and next.

We then presented with the option to save the actions as an SSIS package. We will leave the Save as option unchecked and click next.

Lastly, we will see a verification screen, which explains all that we are about to attempt. If everything looks good, we can execute the Import by clicking on Finish.

We now get to watch the magic happen. The file will import successfully and you will see the number of rows processed. You will also notice some validation warnings.

A successful Import

For the most part, this is SSIS(see below) complaining about the possible truncation of data. You can review these warnings if you wish.

With the import complete, we can query the table and see if the data imported correctly.

And the data looks good! Congratulations! You have imported data via the Import Export Wizard.

* From what I can tell, the Import Export Wizard actually creates an SSIS package that executes the import. By default, SSIS packages are set to fail on truncation and you do not have to option to ignore truncation when you use the Import Export wizard method. In this sample file, some of the columns are longer than the default String 50, which causes the entire import to fail. This even goes for columns that are ignored in the Source-Destination mapping. When defining your source columns, make sure the String types are long enough before attempting an import.

Post to Twitter