【发布时间】:2016-10-03 20:49:04
【问题描述】:
我正在通过带有 DBD::ODBC 的 Perl DBI 模块连接到 SQL Server 2014 数据库。我正在查看的表具有以下结构:
CREATE TABLE [dbo].[JonesFrank$EMSM Printouts](
[timestamp] [timestamp] NOT NULL,
[Document Type] [int] NOT NULL,
[Document No_] [nvarchar](20) NOT NULL,
[Line No_] [int] NOT NULL,
[Entry No_] [int] NOT NULL,
[Printout] [image] NULL,
[Date] [datetime] NOT NULL,
CONSTRAINT [JonesFrank$EMSM Printouts$0] PRIMARY KEY CLUSTERED
(
[Document Type] ASC,
[Document No_] ASC,
[Line No_] ASC,
[Entry No_] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
如您所见,它有一个timestamp 列,巧妙地命名为“时间戳”。当我在 SQL Server 应用程序中从该表中选择值时,它们会以长十六进制数字的形式出现,如下所示:
+====================+
| timestamp |
+====================+
| 0x000000000AA531FB |
| 0x000000000AB0F485 |
| 0x000000000AB0F483 |
| 0x000000000A941C0C |
| 0x000000000AA531F5 |
| 0x000000000AA53448 |
+====================+
但是,当我使用 DBI 和 DBD::ODBC 运行 Perl 程序时,结果是包含不可打印字符的字符串:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Getopt::Long;
GetOptions (
'dbname=s' => \my $dbname,
'driver=s' => \my $driver,
'server=s' => \my $server,
'user=s' => \my $user,
'pwd=s' => \my $pwd,
) or die "Invalid command line options\n";
die "--dbname <database name> required!\n" unless defined $dbname;
$driver //= 'SQL Server';
$server //= 'SQL';
$user //= 'xxx';
$pwd //= 'xxxxxxxx';
my $table = 'TheTable';
my $dbh = DBI->connect(
"dbi:ODBC:Driver={$driver};Server=$server;UID=$user;PWD=$pwd",
{ RaiseError => 1}
) or die "Cannot connect: $DBI::errstr";
$dbh->do("use $dbname");
my $sql = "SELECT [timestamp] FROM [$table] WHERE Printout IS NOT NULL";
my $sth = $dbh->prepare($sql);
$sth->execute();
while (my $row = $sth->fetch()) {
print $row->[0], "\n";
}
(我必须将输出发布为图像,因为我不知道如何重现仅通过在键盘上键入输出的字符串...)
我将 perl 5.22.2 用于 cygwin、DBI.pm 1.636 和 DBD/ODBC.pm 1.52。
有谁知道为什么会出现这样的时间戳值,以及如何获取我在 SQL Server 应用程序中看到的“真实”值?
【问题讨论】:
-
@Stivan:我没有看到您的编辑有任何改进:原始代码可读且缩进很好。但是,在您的三个同行审核您的更改之前,您的提案已阻止任何人进行任何更改。请注意您下次编辑的表现形式
-
我猜你认为时间戳是代表日期和/或时间的东西。如果是这样的话,那么Timestamps aren't what you think they are .
-
看起来该列正在作为压缩的 32 位二进制数检索。如果您使用
print unpack 'N', $row->[0], "\n";,请显示输出。如果这会产生奇怪的结果,请选择print unpack 'V', $row->[0], "\n";。但是您看到的将类似于序列号或访问计数;除非您想比较它们,否则它的值通常没有用,最好留给数据库引擎 -
@ConradFrix 实际上我并不这么认为,因为 SQL Server 向我显示了长的十六进制数字。我不知道它们是什么,但不,我不认为它们是日期和时间。
-
@Borodin 每行都给我 0。
标签: sql sql-server perl cygwin dbi