为什么根据检索顺序从 ADO Recordset 中提取空值而不是正确值? (DB table 有 NTEXT 值)
Why are null values fetched from ADO Recordset instead of correct ones depending on the order of retrieval? (The DB table has NTEXT values)
我有一个数据库 table,其中有两个 datetime 可为空的列,我需要使用 VBScript 从 ASP 页面读取这些列。
这是我写的代码:
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.Prepared = True
.CommandText = "SELECT * FROM storico_corsi WHERE stc_id = 5 "
Set rs = .Execute
Response.Write("stc_scadenza = {" & rs("stc_scadenza") & "}, ")
Response.Write("stc_inizio = {" & rs("stc_inizio") & "} ")
If IsEmpty(rs("stc_inizio")) Then
Response.Write("- ERROR!")
End If
End With
此代码给出此输出:
stc_scadenza = {19/04/2014}, stc_inizio = {} - ERROR!
如果我把检索顺序调换成
...
Response.Write("stc_inizio = {" & rs("stc_inizio") & "}, ")
Response.Write("stc_scadenza = {" & rs("stc_scadenza") & "} ")
...
这是我得到的(正确的)结果:
stc_inizio = {19/02/2014}, stc_scadenza = {19/04/2014}
为什么从 ADO 记录集中检索元素的顺序稍作改变就会产生完全不同的结果?
请注意,我使用的是意大利语言环境 (dd/mm/yyyy) 以及 stc_inizio
和 stc_scadenza
,同时经常设置到午夜时间戳,属于 SQL 类型 datetime.
更新 #1:我通过将代码简化为仅处理两个字段、添加空性检查并删除 JSON 内容,使代码更简单、更清晰共。下面的一些评论涉及以前的更复杂的版本。
更新 #2:如果我将 SQL 查询替换为
SELECT stc_inizio, stc_scadenza FROM storico_corsi WHERE stc_id = 5
或
SELECT stc_scadenza, stc_inizio FROM storico_corsi WHERE stc_id = 5
它工作正常!但为什么?这是我正在使用的数据库 table:
CREATE TABLE [dbo].[storico_corsi] (
[stc_id] [bigint] IDENTITY(1,1) NOT NULL,
[stc_id_ute] [bigint] NOT NULL,
[stc_utente] [varchar](100) NULL,
[stc_anagrafica] [ntext] NULL,
[stc_id_can] [bigint] NULL,
[stc_canale] [varchar](500) NULL,
[stc_FE_id] [bigint] NULL,
[stc_quest_finale] [ntext] NULL,
[stc_quest_corretto] [ntext] NULL,
[stc_reg_fad] [ntext] NULL,
[stc_inizio] [datetime] NULL,
[stc_scadenza] [datetime] NULL,
[stc_terminato] [char](1) NULL
CONSTRAINT [DF_storico_corsi_stc_terminato_1] DEFAULT ('N'),
[stc_fine] [datetime] NULL,
[stc_tempo] [bigint] NULL
CONSTRAINT [DF_storico_corsi_stc_tempo] DEFAULT ((0)),
[stc_data_in] [datetime] NULL
CONSTRAINT [DF_storico_corsi_stc_data_in_1] DEFAULT (getdate()),
[stc_progressivo] [int] NULL,
[stc_anno] [int] NULL,
CONSTRAINT [PK_storico_corsi] PRIMARY KEY CLUSTERED ([stc_id] 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]
更新 #3:只要我在查询中包含 3 个 ntext 列中的任何一个,就可以重现该问题。如果我不 SELECT
他们,没有什么不好的事情发生。显然,ntext 值打破了记录,但它们也以一种不可预测的table 方式做到这一点,这取决于其他字段的检索顺序。
更新 #4:BLOBs/ntexts 必须最后用 ADO 获取。这个说法听起来有点疯狂,但这是我在这里发现的:http://p2p.wrox.com/sql-server-2000/3211-cant-pull-data-ntext-field-into-recordset.html#post78234 这与我的经验一致。
鉴于我们进一步调查后您看到的结果,问题似乎源于您使用 SELECT * ...
隐式选择的 NTEXT
列(但不是使用。)
正如您所指出的,occasional hints on the web 至少在使用 ADO 时检索早于 SELECT 列表末尾的大型二进制字段时存在问题。 (一旦你链接到那篇文章,我确实对模糊而遥远的过去有了模糊的记忆,我以前也看过那个建议。)
我怀疑您可能使用的是旧版本的 ADO,并且此问题可能已在以后的版本中得到修复。
鉴于在这种特殊情况下您实际上并不想从 NTEXT
列中检索值,您应该将 SELECT
列表限制为您实际需要的值,以及所有内容应该可以正常工作。
请注意,通常认为最好的做法是避免使用 SELECT *
,除非是快速的临时查询。明确选择您需要的列有几个好处。例如,在这种情况下,即使您的 SELECT
工作完美,您仍然只能从数据库中检索 NTEXT
字段中可能存在的大量数据(可能通过网络)丢弃它而不使用它...
另请注意,在 KB article 317016, "How To Read and Write BLOBs Using GetChunk and AppendChunk" 中,有一些 "suggestions for using BLOBs with ADO",包括:
- Select the BLOB columns last. Select individual fields, not "*".
我有一个数据库 table,其中有两个 datetime 可为空的列,我需要使用 VBScript 从 ASP 页面读取这些列。
这是我写的代码:
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.Prepared = True
.CommandText = "SELECT * FROM storico_corsi WHERE stc_id = 5 "
Set rs = .Execute
Response.Write("stc_scadenza = {" & rs("stc_scadenza") & "}, ")
Response.Write("stc_inizio = {" & rs("stc_inizio") & "} ")
If IsEmpty(rs("stc_inizio")) Then
Response.Write("- ERROR!")
End If
End With
此代码给出此输出:
stc_scadenza = {19/04/2014}, stc_inizio = {} - ERROR!
如果我把检索顺序调换成
...
Response.Write("stc_inizio = {" & rs("stc_inizio") & "}, ")
Response.Write("stc_scadenza = {" & rs("stc_scadenza") & "} ")
...
这是我得到的(正确的)结果:
stc_inizio = {19/02/2014}, stc_scadenza = {19/04/2014}
为什么从 ADO 记录集中检索元素的顺序稍作改变就会产生完全不同的结果?
请注意,我使用的是意大利语言环境 (dd/mm/yyyy) 以及 stc_inizio
和 stc_scadenza
,同时经常设置到午夜时间戳,属于 SQL 类型 datetime.
更新 #1:我通过将代码简化为仅处理两个字段、添加空性检查并删除 JSON 内容,使代码更简单、更清晰共。下面的一些评论涉及以前的更复杂的版本。
更新 #2:如果我将 SQL 查询替换为
SELECT stc_inizio, stc_scadenza FROM storico_corsi WHERE stc_id = 5
或
SELECT stc_scadenza, stc_inizio FROM storico_corsi WHERE stc_id = 5
它工作正常!但为什么?这是我正在使用的数据库 table:
CREATE TABLE [dbo].[storico_corsi] (
[stc_id] [bigint] IDENTITY(1,1) NOT NULL,
[stc_id_ute] [bigint] NOT NULL,
[stc_utente] [varchar](100) NULL,
[stc_anagrafica] [ntext] NULL,
[stc_id_can] [bigint] NULL,
[stc_canale] [varchar](500) NULL,
[stc_FE_id] [bigint] NULL,
[stc_quest_finale] [ntext] NULL,
[stc_quest_corretto] [ntext] NULL,
[stc_reg_fad] [ntext] NULL,
[stc_inizio] [datetime] NULL,
[stc_scadenza] [datetime] NULL,
[stc_terminato] [char](1) NULL
CONSTRAINT [DF_storico_corsi_stc_terminato_1] DEFAULT ('N'),
[stc_fine] [datetime] NULL,
[stc_tempo] [bigint] NULL
CONSTRAINT [DF_storico_corsi_stc_tempo] DEFAULT ((0)),
[stc_data_in] [datetime] NULL
CONSTRAINT [DF_storico_corsi_stc_data_in_1] DEFAULT (getdate()),
[stc_progressivo] [int] NULL,
[stc_anno] [int] NULL,
CONSTRAINT [PK_storico_corsi] PRIMARY KEY CLUSTERED ([stc_id] 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]
更新 #3:只要我在查询中包含 3 个 ntext 列中的任何一个,就可以重现该问题。如果我不 SELECT
他们,没有什么不好的事情发生。显然,ntext 值打破了记录,但它们也以一种不可预测的table 方式做到这一点,这取决于其他字段的检索顺序。
更新 #4:BLOBs/ntexts 必须最后用 ADO 获取。这个说法听起来有点疯狂,但这是我在这里发现的:http://p2p.wrox.com/sql-server-2000/3211-cant-pull-data-ntext-field-into-recordset.html#post78234 这与我的经验一致。
鉴于我们进一步调查后您看到的结果,问题似乎源于您使用 SELECT * ...
隐式选择的 NTEXT
列(但不是使用。)
正如您所指出的,occasional hints on the web 至少在使用 ADO 时检索早于 SELECT 列表末尾的大型二进制字段时存在问题。 (一旦你链接到那篇文章,我确实对模糊而遥远的过去有了模糊的记忆,我以前也看过那个建议。)
我怀疑您可能使用的是旧版本的 ADO,并且此问题可能已在以后的版本中得到修复。
鉴于在这种特殊情况下您实际上并不想从 NTEXT
列中检索值,您应该将 SELECT
列表限制为您实际需要的值,以及所有内容应该可以正常工作。
请注意,通常认为最好的做法是避免使用 SELECT *
,除非是快速的临时查询。明确选择您需要的列有几个好处。例如,在这种情况下,即使您的 SELECT
工作完美,您仍然只能从数据库中检索 NTEXT
字段中可能存在的大量数据(可能通过网络)丢弃它而不使用它...
另请注意,在 KB article 317016, "How To Read and Write BLOBs Using GetChunk and AppendChunk" 中,有一些 "suggestions for using BLOBs with ADO",包括:
- Select the BLOB columns last. Select individual fields, not "*".