如何使用 ODBC 写入 varchar(max) 列

发布于 2024-07-25 19:51:12 字数 1506 浏览 1 评论 0原文

摘要:我正在尝试使用 ODBC 和 SQL Server 2005 将文本字符串写入 varchar(max) 类型的列。如果字符串的长度大于 8000,则会失败。救命!

我有一些使用 ODBC(SQL Native Client)将文本字符串写入表的 C++ 代码。 如果我将列从 varchar(100) 更改为 varchar(max) 并尝试写入长度大于 8000 的字符串,则写入失败并出现以下错误

[Microsoft][ODBC SQL Server Driver]字符串数据,右截断

那么,谁能告诉我这是否可以完成,以及如何完成?

一些示例(生产)代码显示了我正在尝试执行的操作:

SQLHENV hEnv = NULL;
SQLRETURN iError = SQLAllocEnv(&hEnv);

HDBC hDbc = NULL;
SQLAllocConnect(hEnv, &hDbc);

const char* pszConnStr = "Driver={SQL Server};Server=127.0.0.1;Database=MyTestDB";
UCHAR szConnectOut[SQL_MAX_MESSAGE_LENGTH];
SWORD iConnectOutLen = 0;
iError = SQLDriverConnect(hDbc, NULL, (unsigned char*)pszConnStr,
                      SQL_NTS, szConnectOut,
                      (SQL_MAX_MESSAGE_LENGTH-1), &iConnectOutLen,
                      SQL_DRIVER_COMPLETE);

HSTMT hStmt = NULL;
iError = SQLAllocStmt(hDbc, &hStmt);

const char* pszSQL = "INSERT INTO MyTestTable (LongStr) VALUES (?)";
iError = SQLPrepare(hStmt, (SQLCHAR*)pszSQL, SQL_NTS);

char* pszBigString = AllocBigString(8001);
iError = SQLSetParam(hStmt, 1, SQL_C_CHAR, SQL_VARCHAR, 0, 0, (SQLPOINTER)pszBigString, NULL);

iError = SQLExecute(hStmt);  // Returns SQL_ERROR if pszBigString len > 8000

表 MyTestTable 包含定义为 varchar(max) 的单个列。 函数 AllocBigString(未显示)创建任意长度的字符串。

我知道以前版本的 SQL Server 对 varchars 有 8000 个字符的限制,但不知道为什么在 SQL 2005 中会发生这种情况?

谢谢, 安迪

Summary: I'm trying to write a text string to a column of type varchar(max) using ODBC and SQL Server 2005. It fails if the length of the string is greater than 8000. Help!

I have some C++ code that uses ODBC (SQL Native Client) to write a text string to a table. If I change the column from, say, varchar(100) to varchar(max) and try to write a string with length greater than 8000, the write fails with the following error

[Microsoft][ODBC SQL Server
Driver]String data, right truncation

So, can anyone advise me on if this can be done, and how?

Some example (not production) code that shows what I'm trying to do:

SQLHENV hEnv = NULL;
SQLRETURN iError = SQLAllocEnv(&hEnv);

HDBC hDbc = NULL;
SQLAllocConnect(hEnv, &hDbc);

const char* pszConnStr = "Driver={SQL Server};Server=127.0.0.1;Database=MyTestDB";
UCHAR szConnectOut[SQL_MAX_MESSAGE_LENGTH];
SWORD iConnectOutLen = 0;
iError = SQLDriverConnect(hDbc, NULL, (unsigned char*)pszConnStr,
                      SQL_NTS, szConnectOut,
                      (SQL_MAX_MESSAGE_LENGTH-1), &iConnectOutLen,
                      SQL_DRIVER_COMPLETE);

HSTMT hStmt = NULL;
iError = SQLAllocStmt(hDbc, &hStmt);

const char* pszSQL = "INSERT INTO MyTestTable (LongStr) VALUES (?)";
iError = SQLPrepare(hStmt, (SQLCHAR*)pszSQL, SQL_NTS);

char* pszBigString = AllocBigString(8001);
iError = SQLSetParam(hStmt, 1, SQL_C_CHAR, SQL_VARCHAR, 0, 0, (SQLPOINTER)pszBigString, NULL);

iError = SQLExecute(hStmt);  // Returns SQL_ERROR if pszBigString len > 8000

The table MyTestTable contains a single colum defined as varchar(max). The function AllocBigString (not shown) creates a string of arbitrary length.

I understand that previous versions of SQL Server had an 8000 character limit to varchars, but not why is this happening in SQL 2005?

Thanks,
Andy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哑剧 2024-08-01 19:51:12

您确定加载的是 2005 的 SQL Native Driver,而不是 2000 的旧驱动程序? 2k8 的本机驱动程序名称为 {SQL Server Native Client 10.0}或 2k5 的 {SQL Native Client}

错误消息ODBC SQL Server Driver似乎表明旧的2k驱动程序(我可能是错的,现在已经有10年没有接触过ODBC了)。

You sure you load the SQL Native Driver for 2005, not the old driver for 2000? The native driver name is {SQL Server Native Client 10.0} for 2k8 or {SQL Native Client} for 2k5

The error message ODBC SQL Server Driver seem to indicate the old 2k driver (I may be wrong, haven't touch ODBC in like 10 years now).

意中人 2024-08-01 19:51:12

事实证明,虽然该修复适用于 SQLSetParam,但不适用于 SQLBindParameter。

例如:

int iLength = 18001;
char* pszBigString = new char[iLength + 1];
memset(pszBigString, 'a', iLength);
pszBigString[iLength] = 0;
LONG_PTR lLength = SQL_NTS;
::SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT,
                SQL_C_CHAR,
                SQL_VARCHAR,
                iLength, 0, pszBigString, iLength * sizeof(TCHAR),
                &lLength);

无论使用哪个驱动程序,都会导致相同的 22001“字符串数据,右截断”错误。

事实上,我的实验表明您不需要实际上需要安装版本 10 的客户端驱动程序。 如果您预计字符串的长度超过 8000 个字符,则应使用 SQL_LONGVARCHAR 而不是 SQL_VARCHAR。 您可能会执行大规模查找和替换,但使用 SQL_LONGVARCHAR 可能会招致某种惩罚(尽管这纯粹是猜测;它是“扩展数据类型”)。

我已在 Windows XP 上使用两个驱动程序成功进行了测试:

  • {SQL Server} 2000.85.1117.00 (04/08/2004)
  • {SQL Server Native Client 10.0} 2007.100.1600.22 (10/07/2008)

Turns out that although the fix works for SQLSetParam, it does not work for SQLBindParameter.

For example:

int iLength = 18001;
char* pszBigString = new char[iLength + 1];
memset(pszBigString, 'a', iLength);
pszBigString[iLength] = 0;
LONG_PTR lLength = SQL_NTS;
::SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT,
                SQL_C_CHAR,
                SQL_VARCHAR,
                iLength, 0, pszBigString, iLength * sizeof(TCHAR),
                &lLength);

will result in the same 22001 "String data, right truncation" error, regardless of which driver is used.

In fact, my experiments have shown that you do not actually need to install version 10 of the client driver. Instead you should use SQL_LONGVARCHAR instead of SQL_VARCHAR if you expect the lengths of your strings to exceed 8000 characters. You could potentially perform a mass find-and-replace, but it's possible that using SQL_LONGVARCHAR might incur some sort of penalty (although that's pure speculation; it's an 'extended datatype').

I have tested this successfully with both drivers on Windows XP:

  • {SQL Server} 2000.85.1117.00 (04/08/2004)
  • {SQL Server Native Client 10.0} 2007.100.1600.22 (10/07/2008)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文