DBD for MS SQL Server

jdavidb on 2004-02-05T14:01:30

Anyone know off hand what the "preferred" method for accessing SQL Server from DBI is? Should I be going the ODBC route? Or is SQL Server an assimilated product with another former name for which a DBD exists?


DBD::ODBC

gtod on 2004-02-05T14:58:46

We use DBD::ODBC and have been very happy. We connect like this (took me a while to work out so hope this helps...)

my $dsn = join "", (
"dbi:ODBC:",
"Driver={SQL Server};",
"Server=gort;",
"UID=gpd;",
"PWD=gpd;",
"Database=gort_db",
);

my $user = 'gpd';
my $passwd = 'gpd';

my $db_options = {
PrintError => 1,
RaiseError => 1,
AutoCommit => 0, #Use transactions
};

my $dbh =
DBI->connect($dsn, $user, $passwd, $db_options)
or exit_msg("Can't connect: $DBI::errstr");

Sorry about the formatting. The 'code' tag doesn't do what I'd like...

Re:DBD::ODBC

jdavidb on 2004-02-05T15:19:18

Thanks for the help, and even more for the sample code! You'll probably find pudge's wonderful ecode tag will help you out.

Re:DBD::ODBC

runrig on 2004-02-05T18:34:13

You realize, of course, that with RaiseError set, your code will never hit that call to exit_msg(), die'ing before it gets there if there are any problems with the connect.

Re:DBD::ODBC

grantm on 2004-02-06T05:07:42

You realize, of course, that with RaiseError set, your code will never hit that call to exit_msg()

That certainly hasn't been my experience - perhaps things have changed with recent versions of DBI. I understood that RaiseError was a property of the database handle object which wouldn't exist until the connect method had returned successfully. Errors during the connect itself are handled by returning undef and storing the error message in $DBI::errstr.

Re:DBD::ODBC

jdavidb on 2004-02-06T14:10:55

I think you have misunderstood. My understanding is that if you have RaiseError set in the options you pass to the connect method, connect will die if unsuccessful. I just ran a short experiment to check, and it is true for Oracle, at least when you attempt to log in to an instance with an incorrect password. YMMV with other drivers or other specific errors, I suppose.

I now connect always with RaiseError => 1, PrintError => 0 (to avoid duplicates; DBI docs say to do this, btw), and AutoCommit => 0.

Re:DBD::ODBC

runrig on 2004-02-06T18:11:34

perhaps things have changed with recent versions of DBI.

It probably was different at one time. Found this in the Change log:

Changes in DBI 0.91,    10th December 1997

  NOTE: This fix may break some existing scripts:
  DBI->connect("dbi:...",$user,$pass) was not setting AutoCommit and PrintError!
  DBI->connect(..., { ... }) no longer sets AutoCommit or PrintError twice.
  DBI->connect(..., { RaiseError=>1 }) now croaks if connect fails.

Re:DBD::ODBC

grantm on 2004-02-06T20:25:12

Thanks very much for that piece of detective work. The 'or die' on my connect calls is obviously a piece of baggage I've been carrying far too long.

Re:DBD::ODBC

jdavidb on 2004-02-06T21:02:23

You must undergo the cleansing ritual of purging cargo cult code!!! :)

Could be worse. I still deal with programs from people who wrote open FILE, "$filename" || die "Cant open file", leaving the apostrophe out of can't because they never understood the difference between single and double quotes, and the folklore persisted to nearly every programmer here except me that you couldn't use contractions in the die statement...

DBD::Sybase ...

derby on 2004-02-05T16:39:12

... should work. MS-SQL was orignally SYBASE and both MS-SQL and SYBASE "talk" via TDS. Of course there are some gotchas (just google dbd sybase ms-sql).

Re:DBD::Sybase ...

jdavidb on 2004-02-05T18:19:27

Thanks. I thought I had heard something like that, but couldn't remember that Sybase was the DBMS in question, so I couldn't find anything with google.

DBD::ODBC

runrig on 2004-02-05T17:20:21

It took me awhile to figure out, but whenever I need to connect to several different databases of the same type through DBD::ODBC, I create a file dsn for the first one, then copy and paste the contents of the file (from c:\Program Files\Common Files\ODBC) into the program to use as a template. E.g., for SQL server (on my local machine) it was:
my $dsn=<<EOT;
DRIVER=SQL Server
DATABASE=$dbname
APP=Microsoft Open Database Connectivity
SERVER=(local)
Description=paxl
EOT

$dsn =~ tr/\n/;/;
my $dbh = DBI->connect("dbi:ODBC:$dsn", 'sa', '', {RaiseError=>1});
(as you can see I have very secure login and passwords :-)

Re:DBD::ODBC

runrig on 2004-02-05T17:33:44

I should also mention that you can create a system dsn and just use that name directly in the "dbi:ODBC:$dsn" string, but that gets to be a hassle when there are alot of databases, or if you need to port the code to another machine(s) where the dsn's are not set up.

If you mean from Linux...

Matts on 2004-02-05T21:29:29

Then here's another vote for DBD::ODBC.

I started off using DBD::Sybase, but it has some problems (with exceptions IIRC) when talking to MS SQL Server.

For the ODBC layer I use unixODBC and of course freeTDS.

Re:If you mean from Linux...

jdavidb on 2004-02-06T13:55:54

So either way I'm going to need to install freeTDS. Looks like I need to start there.

This is from Solaris, if it makes any difference. (All Unices are the same to me, though; and usually to the code.)