RODBC不会从数据帧中保存大于8k的varchar / text

时间:2013-08-28 01:26:55

标签: r rodbc

我正在抓取网页数据,一些结果超过8K的文字。我的MS SQL Server 2008 R2中有一个varchar(max)字段,但RODBC只保存8K并截断其余字段。我使用SS R2的SQL Native Client 10和ODBC 11设置了DSN连接。

sqlType为字段标题返回-1,表示varchar(max)/ text。

两个连接都会在8K处截断文本。是否有针对此的修复/解决方法或我在SQL Server中限制为8K?如果R mySQL驱动程序将传递更大量的文本,我可以切换到MySQL。我在Win 7 x64上使用R 3.0.1和RODBC 1.3-6。

以下是一些用于复制问题的示例代码。

CREATE TABLE
[test](
[title] [varchar](max) NULL
) ON [PRIMARY]


library(RODBC)
ch <- odbcConnect("text", uid = "X", pwd = "X")
sqlTypeInfo(ch,"test")

testtext = data.frame("salasjflsjsf")
colnames(testtext) = "title"

## This works
sqlSave(ch,testtext,"test",append=TRUE, rownames=FALSE, colnames = FALSE, safer=FALSE,  verbose = TRUE)


## text > 8K
testtext = data.frame(paste(rep("salasjflsjsf",5000),collapse=""))
colnames(testtext) = "title"

## use ODBC default type for title
sqlSave(ch,testtext,"test",append=TRUE, rownames=FALSE, colnames = FALSE, safer=FALSE,  verbose = TRUE)

## this message from ODBC
## Query: INSERT INTO "test" ( "title" ) VALUES ( ? )
## Binding: 'title' DataType 12, ColSize 8000
## Parameters:
## no: 1: title salasjfl
## [*text removed*]
## lsjsfsalasjflsjsfsalasjflsjsfsalasjflsjsfsalasjflsjsfsalasjflsjsfsalasjflsjsf/***/
## Warning message:
## In odbcUpdate(channel, query, mydata, coldata[m, ], test = test,  :
##   character data 'salasjflsjsfsalasjflsjsfsalasjflsjsfsalasjfl




## try with varType set to text
sqlSave(ch,testtext,"test",append=TRUE, varType = "text",rownames=FALSE, colnames = FALSE, safer=FALSE,  verbose = TRUE)

## try with varType set to varchar(MAX)
sqlSave(ch,testtext,"test",append=TRUE, varType = "varchar(max)",rownames=FALSE, colnames = FALSE, safer=FALSE,  verbose = TRUE)

close(ch)

我将列类型更改为文本并刷新了DSN连接。正在拾取文本类型,但现在出现错误消息:

 chtest <-odbcConnect("test2", uid = "X", pwd = "X")
    > sqlColumns(chtest,"test")
      TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_SIZE BUFFER_LENGTH DECIMAL_DIGITS NUM_PREC_RADIX NULLABLE REMARKS
    1   RSS            dbo       test       title        -1      text  2147483647    2147483647             NA             NA        1    <NA>
      COLUMN_DEF SQL_DATA_TYPE SQL_DATETIME_SUB CHAR_OCTET_LENGTH ORDINAL_POSITION IS_NULLABLE SS_IS_SPARSE SS_IS_COLUMN_SET SS_IS_COMPUTED
    1       <NA>            -1               NA        2147483647                1         YES            0                0              0
      SS_IS_IDENTITY SS_UDT_CATALOG_NAME SS_UDT_SCHEMA_NAME SS_UDT_ASSEMBLY_TYPE_NAME SS_XML_SCHEMACOLLECTION_CATALOG_NAME
    1              0                <NA>               <NA>                      <NA>                                 <NA>
      SS_XML_SCHEMACOLLECTION_SCHEMA_NAME SS_XML_SCHEMACOLLECTION_NAME SS_DATA_TYPE
    1                                <NA>                         <NA>           35
    > sqlSave(chtest,testtext,"test",append=TRUE, varType = "text",rownames=FALSE, colnames = FALSE, safer=FALSE,  verbose = TRUE)
    Query: INSERT INTO "test" ( "title" ) VALUES ( ? )
    Binding: 'title' DataType -1, ColSize 2147483647
    Error in odbcUpdate(channel, query, mydata, coldata[m, ], test = test,  : 
      'Calloc' could not allocate memory (18446744071562067968 of 1 bytes)
    In addition: Warning messages:
    1: In odbcUpdate(channel, query, mydata, coldata[m, ], test = test,  :
      Reached total allocation of 6013Mb: see help(memory.size)
    2: In odbcUpdate(channel, query, mydata, coldata[m, ], test = test,  :
      Reached total allocation of 6013Mb: see help(memory.size)

2 个答案:

答案 0 :(得分:1)

您将文本列定义为varchar(max)类型,因此无论在保存数据时指定varType,它都将以这种方式存储。

尝试创建一个包含TEXT列的表格,然后使用sqlSave。这样,数据将存储在行上下文之外,您不应该有截断问题。

答案 1 :(得分:0)

我遇到了类似的问题,最后做了以下事情:

# Finding the longest character
varTypes = c(col_in_question=sprintf("varchar(%s)", max(nchar(data$col_in_question))))

# Uploading data
sqlSave(channel = dbhandle, 
        dat = data, 
        tablename = "data_name",
        rownames = FALSE,
        varTypes = varTypes)

通过这种方式,您可以将varchar设置为数据集中的max,如果没有任何超长字符(2 Gb),它应该可以正常工作。如果你坚持使用varchar(max),那么你可以使用sqlQuery在数据集中更改它。