- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我支持用 MFC/C++ 编写的旧版应用程序。该应用程序的数据库位于 SQL Server 2000 中。我们最近加入了一些新功能,发现当我们将 SQL 提供程序从 SQLOLEDB.1 更改为 SQLNCLI.1 时,一些代码试图通过存储过程从表中检索数据失败。
有问题的表非常简单,是通过以下脚本创建的:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UAllergenText](
[TableKey] [int] IDENTITY(1,1) NOT NULL,
[GroupKey] [int] NOT NULL,
[Description] [nvarchar](150) NOT NULL,
[LanguageEnum] [int] NOT NULL,
CONSTRAINT [PK_UAllergenText] PRIMARY KEY CLUSTERED
(
[TableKey] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[UAllergenText] WITH CHECK ADD CONSTRAINT
FK_UAllergenText_UBaseFoodGroupInfo] FOREIGN KEY([GroupKey])
REFERENCES [dbo].[UBaseFoodGroupInfo] ([GroupKey])
GO
ALTER TABLE [dbo].[UAllergenText] CHECK CONSTRAINT
FK_UAllergenText_UBaseFoodGroupInfo]
基本上是四列,其中 TableKey 是标识列,其他所有内容都通过以下脚本填充:
INSERT INTO UAllergenText (GroupKey, Description, LanguageEnum)
VALUES (401, 'Egg', 1)
在上面的之后还有一长串其他 INSERT INTO。插入的一些行在其描述中有特殊字符(如字母上方的重音符号)。我最初认为包含特殊字符是问题的一部分,但如果我完全清除表格,然后仅使用上面没有特殊字符的单个 INSERT INTO 重新填充它,它仍然会失败。
所以我继续...
然后通过以下代码访问此表中的数据:
std::wstring wSPName = SP_GET_ALLERGEN_DESC;
_variant_t vtEmpty1 (DISP_E_PARAMNOTFOUND, VT_ERROR);
_variant_t vtEmpty2(DISP_E_PARAMNOTFOUND, VT_ERROR);
_CommandPtr pCmd = daxLayer::CDataAccess::GetSPCommand(pConn, wSPName);
pCmd->Parameters->Append(pCmd->CreateParameter("@intGroupKey", adInteger, adParamInput, 0, _variant_t((long)nGroupKey)));
pCmd->Parameters->Append(pCmd->CreateParameter("@intLangaugeEnum", adInteger, adParamInput, 0, _variant_t((int)language)));
_RecordsetPtr pRS = pCmd->Execute(&vtEmpty1, &vtEmpty2, adCmdStoredProc);
//std::wstring wSQL = L"select Description from UAllergenText WHERE GroupKey = 401 AND LanguageEnum = 1";
//_RecordsetPtr pRS = daxLayer::CRecordsetAccess::GetRecordsetPtr(pConn,wSQL);
if (pRS->GetRecordCount() > 0)
{
std::wstring wDescField = L"Description";
daxLayer::CRecordsetAccess::GetField(pRS, wDescField, nameString);
}
else
{
nameString = "";
}
daxLayer 是应用程序正在使用的第三方数据访问库,尽管我们有它的源代码(其中一些将在下面看到。)SP__GET_ALLERGEN_DESC 是用于从表中获取数据的存储过程,它是通过这个脚本创建的:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spRET_AllergenDescription]
-- Add the parameters for the stored procedure here
@intGroupKey int,
@intLanguageEnum int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT Description FROM UAllergenText WHERE GroupKey = @intGroupKey AND LanguageEnum = @intLanguageEnum
END
当 SQL Provider 设置为 SQLNCLI.1 时,应用程序崩溃:
daxLayer::CRecordsetAccess::GetField(pRS, wDescField, nameString);
来自上面的代码片段。所以我进入了 GetField,它看起来像下面这样:
void daxLayer::CRecordsetAccess::GetField(_RecordsetPtr pRS,
const std::wstring wstrFieldName, std::string& sValue, std::string sNullValue)
{
if (pRS == NULL)
{
assert(false);
THROW_API_EXCEPTION(GetExceptionMessageFieldAccess(L"GetField",
wstrFieldName, L"std::string", L"Missing recordset pointer."))
}
else
{
try
{
tagVARIANT tv = pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value;
if ((tv.vt == VT_EMPTY) || (tv.vt == VT_NULL))
{
sValue = sNullValue;
}
else if (tv.vt != VT_BSTR)
{
// The type in the database is wrong.
assert(false);
THROW_API_EXCEPTION(GetExceptionMessageFieldAccess(L"GetField",
wstrFieldName, L"std::string", L"Field type is not string"))
}
else
{
_bstr_t bStr = tv ;//static_cast<_bstr_t>(pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value);
sValue = bStr;
}
}
catch( _com_error &e )
{
RETHROW_API_EXCEPTION(GetExceptionMessageFieldAccess(L"GetField",
wstrFieldName, L"std::string"), e.Description())
}
catch(...)
{
THROW_API_EXCEPTION(GetExceptionMessageFieldAccess(L"GetField",
wstrFieldName, L"std::string", L"Unknown error"))
}
}
}
这里的罪魁祸首是:
tagVARIANT tv = pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value;
进入 Fields->GetItem 将我们带到:
获取元素
inline FieldPtr Fields15::GetItem ( const _variant_t & Index ) {
struct Field * _result = 0;
HRESULT _hr = get_Item(Index, &_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return FieldPtr(_result, false);
}
然后将我们带到:
获取值(value)
inline _variant_t Field20::GetValue ( ) {
VARIANT _result;
VariantInit(&_result);
HRESULT _hr = get_Value(&_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _variant_t(_result, false);
}
如果您在运行时单步执行此操作时查看 _result,则 _result 的 BSTR 值是正确的,其值为表“描述”字段中的“Egg”。继续逐步跟踪所有 COM 发布调用等。当我最终回到:
tagVARIANT tv = pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value;
然后越过它到下一行,tv 的内容现在应该是 BSTR="Egg":
tv BSTR = 0x077b0e1c "ᎀݸﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ㨼㺛帛᠄"
当 GetField 函数尝试将其返回值设置为 tv.BSTR 中的值时
_bstr_t bStr = tv;
sValue = bStr;
不出所料,它窒息而死。
那么 BSTR 的值发生了什么变化,为什么它只在提供程序设置为 SQLNCLI.1 时发生?
说到底,我在最上面的代码中注释掉了使用存储过程,并硬编码了存储过程使用的相同 SQL SELECT 语句,发现它工作正常并且返回的值是正确的。
此外,用户还可以通过应用程序向表中添加行。如果应用程序在该表中创建一个新行并通过存储过程检索该行,它也可以正常工作,除非您在描述中包含一个特殊字符,在这种情况下它可以正确保存该行但再次以与上述完全相同的方式爆炸在检索该行时。
总而言之,如果可以的话,通过 INSERT 脚本放入表中的行在被存储过程访问时总是会破坏应用程序(无论它们是否包含任何特殊字符)。用户在运行时从应用程序内部放入表中的行可以通过存储过程正确检索,除非它们在描述中包含特殊字符,此时它们会破坏应用程序。如果您在运行时使用代码中的 SQL 而不是存储过程来访问表中的任何行,那么无论描述中是否有特殊字符,它都可以正常工作。
如果能对此有所启发,我们将不胜感激,在此先感谢您。
最佳答案
这一行可能有问题:
tagVARIANT tv = pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value;
如果我没看错,->Value 返回一个 _variant_t,它是一个智能指针。智能指针将在超出范围时释放它的变体,就在这一行之后。但是,tagVARIANT 不是智能指针,因此在分配给它时不会增加引用计数。所以在这一行之后,tv 可能指向一个已经有效发布的变体。
如果你这样写代码会发生什么?
_variant_t tv = pRS->Fields->GetItem(_variant_t(wstrFieldName.c_str()))->Value;
或者,告诉智能指针不要释放它的负载:
_tagVARIANT tv = pRS->Fields->GetItem(
_variant_t(wstrFieldName.c_str()))->Value.Detach();
我已经很久没有用 C++ 编写代码了,读了这篇文章,我不后悔搬走!
关于c++ - 将 SQL Provider 从 SQLOLEDB.1 更改为 SQLNCLI.1 会导致应用程序在通过存储过程访问数据时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/858624/
如果我声明了类似的类型 type test(NSIZE) integer, len :: NSIZE real :: dummy(NSIZE) contains procedure,
我知道这是一个不太可能的事情,但是由于“选项私有(private)模块”的限制,甚至更糟糕的“私有(private)子/函数”的限制,有谁知道是否有一种方法可以从 Excel 应用程序隐藏 VBA 过
我有两个表,property 和 component。 component.id_property = property.id。 我正在尝试创建一个过程,该过程对所选属性的组件进行计数,如果所选属性没
我有一份报告,它是在 SSRS 2005 中开发的,我正在使用存储过程从数据库中获取结果。报告输出的结果非常简单,如下图所示。 如果假设我正在寻找不同的成员 例如:- MemberID c108 c
我需要一个通用函数/过程,该函数/过程将根据提供的数据计算出我的淡入淡出时间和值,如下所示: 我将字节值保存在字节数组中:这些是起始值。然后,我在其他数组中存储了一些值:这些将是新值。然后我有时间要提
我想在界面的多个按钮上创建相同的操作。是否只能通过创建单独的操作监听器方法并调用执行操作的方法才可行,还是还有其他方法?是否可以将按钮放在一个组中并执行以下操作:- groupButton.setOn
我有以下情况: procedure Test; begin repeat TryAgain := FALSE; try // Code // Code if this an
我正在尝试执行以下操作;假设我在 Oracle 中创建了一个对象类型 create type test as object( name varchar2(12), member procedure p
问题: 如果可能的话,如何声明一个用于任何类型参数的函数 T其中 T 的唯一约束是它被定义为 1D array如 type T is array ( integer range <> ) of a_r
我正在尝试创建这个 mysql 过程来制作一个包含今年所有日期和所有时间的表(以一小时为间隔。) CREATE TABLE FECHAS ( created_at datetime ); CREA
所以, 我在这里面临一个问题,这让我发疯,我认为这是一个愚蠢的错误,所以我不是 MySQL 的新手,但它并不像我想象的那样工作。 尝试将此语句部署到 MySQL 后,我收到此错误: ERROR 106
我有一个架构,其中包含星球大战中的人物列表、他们出现的电影、他们访问的行星等。这是架构: CREATE DATABASE IF NOT EXISTS `starwarsFINAL` /*!40100
我一直在为一家慈善机构创建一款应用程序,允许家庭在节日期间注册接收礼物。数据库组织有多个表。下面列出了这些表(及其架构/创建语句): CREATE TABLE IF NOT EXISTS ValidD
正如上面标题所解释的,我正在尝试编写一个sql函数来按日期删除表而不删除系统表。我在此消息下方放置了一张图片,以便直观地解释我的问题。任何帮助将不胜感激!感谢您的时间! 最佳答案 您可以通过查询INF
DELIMITER $$ CREATE PROCEDURE INSERT_NONE_HISTORY_CHECKBOX() BEGIN DECLARE note_id bigint(20); F
是否可以编写一个存储过程或触发器,在特定时间在数据库内部自动执行,而无需来自应用程序的任何调用?如果是,那么任何人都可以给我一个例子或链接到一些我可以阅读如何做到这一点的资源。 最佳答案 查看 pgA
我需要创建一个过程:1)从表中的字段中选择一些文本并将其存储在变量中2) 更新相同的记录字段,仅添加 yyyymmdd 格式的日期以及过程中的附加文本输入...类似这样的... delimiter /
好的,这就是我想做的: 如果条目已存在(例如基于字段name),则只需返回其id 如果没有,请添加 这是我迄今为止所管理的(对于“如果不存在,则创建它”部分): INSERT INTO `object
以下是我编写的程序,用于找出每位客户每天购买的前 10 件商品。 这是我尝试过的第一个 PL/SQL 操作。它没有达到我预期的效果。 我使用的逻辑是接受开始日期、结束日期以及我对每个客户感兴趣的前“x
我正在尝试在MySQL中创建一个过程那insert week s(当年)发送至我的 week table 。但存在一个问题,因为在为下一行添加第一行后,我收到错误: number column can
我是一名优秀的程序员,十分优秀!