When attempting to hide or display an instance of SQL Server over a network, you have a number of different method for doing this.

I found this  particularly problematic when trying to locate a remote SQL server located on a colleague’s workstation. As such, I felt it worthwhile to record and enumerate the different method for doing so.

The scenario was that I was attempting to connect through SSMS (Management Studio) and was getting the error message “Cannot connect to [database name]‘

SQL Server Properties

  1. In Management Studio, click on the server root, and select properties.
  2. From the resulting dialog, select the ‘Connections’ page.
  3. Ensure the checkbox “Allow remote connections to this server” is checked.

SQL Server Configuration

  1. Run SQL Server Configuration Manager (located in within the SQL shortcuts under the windows start menu)
  2. Navigate to “SQL Server Network Configuration” and then “Protocols for SQL2008R2″
  3. Ensure TCP/IP is “Enabled”
  4. Right-click on ”Protocols for SQL2008R2″ and select “Properties”
  5. Ensure “Hide Instance” is set to “no”

 SQL Browser Service

  1. Navigate to the Service Control Manager through control panel (or run “Services.msc”)
  2. Ensure the “SQL Server Browser” service is started. (It may be best to have the Startup Type as “Automatic”

Now, hopefully, you should be able to see the SQL Server instance over the network and connect to it (assuming you have permissions to do so!)

Thanks for the info provided on Stackoverflow in the following articles:

Make MSSQL 2008 Instance invisible (nonpublic)

SQL Server Browser showing only hostname, not instance name

 

 

, ,

I discovered this little trick today.

If you’re wanting to count the number of characters present in a given SQL Server varchar variable, or common, use the following convention

--assuming a search character contained in the variable @SeekChar

--from a variable
SELECT LEN(@StringVariableName) - LEN(REPLACE(@StringVariableName,@SeekChar,''))

--from a table field
SELECT LEN(SomeTableCol) - LEN(REPLACE(SomeTableCol, @SeekChar, ''))
FROM SomeTable

--The Oracle  PL/SQL Variant (for the hell of it).
--All we have to do is replace the LEN function with LENGTH!
SELECT LENTH(SomeTableCol)-LENGTH(REPLACE(SomeTableCol, @SeekChar, ''))
FROM SomeTable

Quick and easy and no annoying looping constructs.

, ,
Problems????

Image by essecento via Flickr

You might be familiar with the following scenario:

You have a SQL Server database server hosting more than one database, but you just so happen to be accessing one in particular from your development environment (Query Analyser, Management Studio, etc).

So, you run a little query to automatically connect you to this database when you connect to the server. You might try something like:

Exec sp_defaultdb @loginame='DOMAIN\UsrNam', @defdb='SomeDatabase';

So, now when you log on, your database is ready and waiting to be used without having to manually select it. I have found this scenario common in development environments, when you are typically running lots of ad-hoc SQL queries, or running in code (stored procedures, views, triggers, etc) against the database.

However if you are working on different databases on the same server, defaulting to a particular one can cause you problems if you need to run in code against a different database. On occasions I have applied stored procedures to the default database, when I meant to do it against another one on the server!

Another consequence is when a development database is refreshed or rebuilt from some external source (from a live environment, for example). Although your default database may exist by name, this is not enough for SQL Server, which fails to log you on and gives the error message:

Cannot open user default database.

You will also get this if you have chosen to rename the database.

So what to do in this instance?

Well, we can defer to the trusty ISQL command line utility, as shown in the following screenshot:

Simply follow these steps:

  1. Open a DOS  command Prompt
  2. Open up an ISQL Session. I used the following command:
    • -S SQLServer_Name – Specify the name of the SQL Server to which you are connecting.
    • -E – Stipulate to connect as a trusted connection (Windows Authentication)
    • -d master – The database name to which you are going to connect. Here I specified ‘master’
  3. isql -S SQLServer_Name -E -d master

    The three options user above are as follows:

    Of course, you can connect however you want. For more options (also shown in the screenshot above), type in isql /? for a full list, or refer to the site on the above link.

  4. Now run a version of the above script, setting the default database to master
  5. Exec sp_defaultdb @loginame='DOMAIN\UsrNam', @defdb='master';
  6. To apply this, enter ‘GO’ on the next line.

This will ensure your SQL Server defaults you to the ‘master’ database in all subsequent connections (unless you change them again). I would counsel this as general good practice, and it comes recommended by a friendly DBA I happen to know.

, , ,

Does that title make any sense to you?

If not, can you bear with me? I’ll make it worth your while, I promise!

I’ve been looking at a bit of code that threw an error for the first time in nearly a year. This ‘bit’ of code is present on four different environments, and is run under some particularly strenuous and varied conditions.

Here is the gist of the code:

SELECT @var = ISNULL((SELECT col1 FROM SomeTable WHERE col2='SomeValue'), 0)

Those gurus (and some lesser mortals) among us will spot the potential problem immediately. For those, this sort of issue sticks out like sore thumb. But, for the rest of us it isn’t so inherently obvious.

Let me demonstrate. Imagine our ‘SomeTable’ has the following data:

Col1 Col2
1 SomeValue
2 SomeValue

We are assuming that statement we are passing to our ISNULL function will only ever return one result. However, in the above example it does not. You can try it yourself; simply paste the SQL below into your query window:

create table #temp (col1 int, col2 varchar(10));
insert into #temp values (1,'SomeValue');
insert into #temp values (2,'SomeValue');
select isnull((select col1 from #temp where col2 = 'SomeValue'),0)
drop table #temp

You should get the following message:

Msg 512, Level 16, State 1, Line 4
Subquery returned more than 1 value. This is not permitted when the subquery
follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Understanding the data is key to resolving this. You have assumed there will only be one value, so what are you prepared to accept? Possible solutions include:

select isnull((select max(col1) from #temp where col2 = 'SomeValue'),0)
select isnull((select min(col1) from #temp where col2 = 'SomeValue'),0)
select isnull((select top 1 col1 from #temp where col2 = 'SomeValue'),0)
select isnull((select distinct col1 from #temp where col2 = 'SomeValue'),0)

The first three solve the problem for you in all cases. In the fourth example, the use of the distinct clause will only work if your result set is identical. In fact, it will still break for our example.

But, by putting one of these fixes in place, we are maybe missing the whole point. Although defensive programming can help trap this sort of error, we are overlooking the fact that we have maybe stumbled upon some sort of data integrity error. I.e. do we have two records where we really shouldn’t?

Then the fix is something more fundamental, for example, are we missing a unique constraint somewhere? Here is our table definition with the constraint:

create table #temp (col1 int, col2 varchar(10), constraint UK_COL2 unique (COL2));

Running our original code block with this in place shows up the error when we try to insert a duplicate value in Col2:

Msg 2627, Level 14, State 1, Line 3
Violation of UNIQUE KEY constraint 'UK_COL2'.
Cannot insert duplicate key in object 'dbo.#temp'.

Sure, we still get the error, however, we get it earlier in our process, which is generally better. The is because we may not query these data for some time after it has been inserted, so it may be some time before the original error presented itself. In addition to this, the chances are that if you’ve coded a unique constraint then you’ll be more inclined to test for it.

So, a few things to think about. Principally, what do you want your subquery to return, and is your data correct?

, , , ,

I’ve been playing around with SSRS in SQL Server 2005 recently, and have been particularly encouraged by its potential as a central reporting tool. As part of this  I have been demonstrating how we can SSRS to produce reports from numerous different data sources and providers.

In this particular instance I have been testing its ability to produce reports from the output of an Oracle Package/Procedure and a SQL Server Stored Procedure.  Using the built-in .NET Client I was able to do this quite successfully with little fuss.

It was then brought to my attention that Microsoft are deprecating Oracle Client from ADO.NET 4. This means that, while the code may continue working for some considerable time, going forward it is a better strategy to use an alternative. So, I switched to using Oracle 11g Release 2 ODAC 11.2.0.1.2.

It’s worth noting that for those wanting to utilise an Oracle Stored procedure in SSRS, it must return its data in an OUT REF CURSOR. There are also a few other conditions which you must abide by.  For further info see: Tap into Oracle Databases with SQL Server Reporting Services.

Anyway, on to the problem…

So, as already intimated, all was fine and dandy, until I switched provider. I had set up the dataset on my report, entered the Stored Procedure name, and clicked ‘Ok’. Nothing happened; the IDE just hung.

At this point, I should probably reproduce the procedure in question:

PROCEDURE pck_mypackage.pr_myproc(L_CURSOR out SYS_REFCURSOR)
is
   BEGIN
     OPEN L_CURSOR FOR
       SELECT * FROM MyTable;
   END;

And here the connection string (missing the credentials).

Provider=OraOLEDB.Oracle.1;Data Source=DBSOURCE

Nothing shocking whatsoever, right?

For the first day or so, I took to killing Visual Studio, tweaking a few settings and then trying again. No-one in the websphere seemed to have encountered this; I was baffled. I even resorted to Window’s Process Monitor and trawling through the 1 million+ events it had logged.

So, I decided to confide in my old friend, the bullet-point list. I regaled it with the details of what was working, and what was not. Here it is, replete with the pertinent information:

What Works?

  • The stored procedure executes correctly in PL/SQL Developer
  • The ‘test connect’ in works fine in SSRS
  • A query string of SELECT * FROM MyTable; with Command Type of ‘text’ produces the correct fields in the SSRS report.
  • .NET Oracle Provider instead of Oracle OLE DB Provider

What Fails:

  • If i change the Command Type to ‘Stored Procedure’ and enter ‘pr_myproc’, when I click ‘OK’ Visual Studio 2005 (service pack 2) simply hangs/crashes.

My attention was drawn to the last three words, “simply hangs/crashes.” It was then I noticed that Visual Studio was not actually hanging completely. I could still click the top-right window buttons; it just seemed to be waiting.

I confided in a friendly DBA, who suggested I looked at the Oracle sessions in an attempt to determine:

  1. Whether or not a connection was actually being made, and,
  2. What it was doing if the connection was successful

Something must have piqued his interest, because he decided to do it there for me himself.

“Ahhh,” he said, “you’re querying sys.obj$.” He then proceeded to explain to me why exactly this was an issue. The schema we were searching had substantially large data dictionary. This dictionary has to be queried in order to bring back the procedure parameters and the REFCURSOR output.  When looking up the information, the two providers (.NET and Oracle) used two different queries that had a dramatic relative difference in their performances.

Here is the one the Oracle Provider used, taking 10+ minutes:

select * from (select null  PROCEDURE_CATALOG
                      , owner PROCEDURE_SCHEMA
                      , object_name PROCEDURE_NAME
                      , decode (object_type, 'PROCEDURE', 2, 'FUNCTION',  3, 1) PROCEDURE_TYPE
                      , null PROCEDURE_DEFINITION
                      , null DESCRIPTION
                      , created DATE_CREATED
                      , last_ddl_time DATE_MODIFIED
              from all_objects where object_type in ('PROCEDURE','FUNCTION')
              union all
              select null PROCEDURE_CATALOG
                          , arg.owner PROCEDURE_SCHEMA
                          , arg.package_name||'.'||arg.object_name PROCEDURE_NAME
                          , decode(min(arg.position), 0, 3, 2) PROCEDURE_TYPE
                          , null PROCEDURE_DEFINITION
                          , decode(arg.overload, '', '', 'OVERLOAD') DESCRIPTION
                          , min(obj.created) DATE_CREATED
                          , max(obj.last_ddl_time) DATE_MODIFIED
              from all_objects obj, all_arguments arg
              where arg.package_name is not null
              and   arg.owner = obj.owner
              and   arg.object_id = obj.object_id
              group by arg.owner, arg.package_name, arg.object_name, arg.overload ) PROCEDURES
WHERE PROCEDURE_NAME = 'pck_my_package.pr_myproc' order by 2, 3

The second SQL Statement in the union is a particular killer. Here, it joins all_objects and all_arguments tables! I actually ran this query in PL/SQL developer, but gave up after it failed to finish in thirty minutes.

This a particular problem of those schemas with large data dictionaries. I tried this in a smaller one, further up our shipping chain, and it returned in an acceptable amount of time.

, , , ,

In an automatic shipping/deployment system you may find yourself having to determine object/item dependencies, and stipulate a shipping order manually.

Controlling IT Costs; Enterprise Architecture ...
Image by Wonderlane via Flickr

For example, when shipping SQL Server code, you might consider the following order of shipping precedence for database scripts:

  1. Structural creation
  2. Structural changes
  3. Relationships
  4. Static Data
  5. Views
  6. Stored Procedures
  7. Triggers

Views that depend on other views have to be shipped in the appropriate order, so you will need to consider this as a factor.

In the background we have a dependency table (sysdepends for SQL 2000 and sys.sql_dependencies for 2005/2008).

For the purposes of this article, I am interested in the creation and omission of records from this table for Stored Procedure dependencies.

So, let us create two simple stored procedures, root and dependent like so:

create procedure root as
select 1
go

create procedure dependent as
exec root
go

So problems anywhere, and the execution of dependent works a treat:

exec dependent;

Moreover, when I look at the sys.sql_dependencies table, I see an entry:

select sd.*
from sys.sql_dependencies sd
inner join sys.objects so on so.object_id = sd.object_id
where so.name = 'dependent'

However, when I add these in reverse (I.e. add the dependent Stored Procedure first), I get the following message:

Cannot add rows to sysdepends for the current stored procedure because it depends on the missing object ‘dependent’

With both stored procedures compiled, the code still works as before, however no entry is added retrospectively to the SQL table when ‘root’ is compiled after ‘dependent’

Although this has no practical impact with regard to execution, your ability to perform effective impact analysis for testing and refactoring purposes.

Fortunately, on SQL2005 and 2008, this can be remedied by executing the sp_refreshsqlmodule stored procedure.

And there we have it!

, ,

Yes, its out there on the web; a SQL Server Database Version Database. Or, to put it differently, a Database of SQL Server Versions.

Here  you can find a list of all the versions of SQL Server that have ever been released. It even goes right back to version 6.0, released in 1995. Check out the SQL Server Release History if you are interested.

I was drawn to this list when I had two database connections open in my object explorer:

SQLDatabase01 (SQL Server 8.0.2050 – Context/UserName)

SQLDatabase02 (SQL Server 8.0.2039 – Context/UserName)

I was curious as to what the difference was, so investigated further and found the SQL Server Version Database. I found the information I wanted with ease:

2000 (GDR) SP4+Q941203 / 948110 – 8.0.2050

2000  SP4 – 8.0.2039

And looking at the hundreds of different versions available, its not surprising that something like this is needed.

,

When I starting writing this blog, I was a little unsure as to what to put in it. I knew I wanted it to be mostly programming related, with articles about things that interested me. So I named it my ‘Programming Notebook’ and put into words exactly what I envisaged I’d be putting in it. This is what I put in my About page:

My main intention was for this blog was to be a notebook for myself in a presentable format – an aid to memory of things I’ve found useful on a day-to-day basis, and little snippets I’d like to share. A lot of it won’t be ground-breaking and you’ll almost certainly find it around elsewhere on the net, but it’s presented in a way that I learned it in the hope that others might find it useful.

And later on I started fretting that I was duplicating what already ‘out there’, which is nonsense, because almost everything that anyone writes is already ‘out there’ anyway.

None of this has anything to do with Identity Inserting in SQL Server, but maybe goes some way to explaining why I am writing about something that is well documented ‘out there’.

The reason is that I had to look it up twice. I needed to look it once, and then I forgot, so I needed to look it up again. What I needed was some sort of programming noteb…. hey… I have one!

So here it is:

SET IDENTITY_INSERT [MyTable] ON
INSERT INTO [MyTable] (IDField, Field2, Field3, Field4) values (1,212,2,2)
SET IDENTITY_INSERT [MyTable] OFF

You’ll need to set IDENTITY_INSERT ‘ON’ for the table into which you are inserting, and (for good measure) set it back to ‘OFF’ when you’re done.

You’ll also need to include a field list (which is good practice anyway). The following just won’t work:

INSERT INTO [MyTable] values (1,212,2,2)

So there we are, SQL Server Identity Inserting covered….again.

,