Inserting into SQL Server VARBINARY column from R script

早过忘川 提交于 2019-12-12 03:56:18

问题


I have a plots table, whose columns include plot, which stores the binary data of an image file. I'm running a T-SQL query which calls an R script and gets back a data frame of the data to insert. The data frame looks like this:

    plot     name  date_from    date_to
1 ABCDEF  plot1   2016-08-25   2016-08-31
2 AAAAAA  plot2   2016-08-25   2016-08-31

As you can see, the plot column contains raw data already.

To clarify, what I want to do is insert two rows into the database with the data in the data frame (the data frame column names match the database columns).

The problem I'm getting with

INSERT INTO dbo.plots
EXECUTE sp_execute_external_script
    @language = N'R'
    ,@script = N'source("path/to/r/script.R")'
    ,@output_data_1_name = N'output_dataset'

is "Implicit conversion from data type nvarchar(max) to varbinary(max) is not allowed. Use the CONVERT function to run this query".

However I'm not sure how I can rectify this error. Where would I put the CONVERT function? Or is there some other way?


回答1:


For SQL Server R services, character type maps to VARCHAR and raw type maps to VARBINARY (see Working with R Data Types). To store data as VARBINARY, the hex string has to be converted to raw bytes, which can be done either in R or SQL. Here is an example with conversion done in SQL using a temporary table (inspired by scsimon's comment)

CREATE TABLE #test
(
    [data] VARBINARY(MAX),
)


CREATE TABLE #temp
(
    [data] VARCHAR(MAX),
)

INSERT INTO #temp
EXEC sp_execute_external_script
@language=N'R',
@script=N'OutputDataSet <- as.data.frame("ABCDEF")' 

INSERT INTO #test SELECT CONVERT(VARBINARY(MAX), data, 2) FROM #temp;



回答2:


Unfortunately, my version of SQL Server doesn't do all the cool R stuff yours does. So the best I can offer is an R Script that can successfully import binary data into a table and hope you are able to make the necessary adaptations.

I'm using a table on SQL Server defined as

CREATE TABLE [dbo].[InsertFile](
    [OID] [int] IDENTITY(1,1) NOT NULL,
    [filename] [varchar](50) NULL,
    [filedata] [varbinary](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

My R script is

library(RODBCext)
library(magrittr)

# My example just grabs all the text files out of a directory,
# but as long as you have the full filename, this will work.

file_name <- list.files([directory_to_files],
                        pattern = "[.]txt$",
                        full.names = TRUE)

file_content <- 
  vapply(
    file_name,
    function(x)
    {
      # read the binary data from the file
      readBin(x,
              what = "raw",
              n = file.info(x)[["size"]]) %>%
        # convert the binary data to a character string suitable for import
        as.character() %>%
        paste(collapse = "")
    },
    character(1)
  )

channel <- odbcConnect(...) # Create your connection object here

sqlExecute(
  channel = channel,
  query = paste0("INSERT INTO dbo.InsertFile ",
                 "(filename, filedata) ",
                 "VALUES ",
                 "(?, ?)"),
  data = list(filename = basename(file_name),
              filedata = file_content)
)

After executing that script, I have a new line in my dbo.InsertFile table for each file in file_name.



来源:https://stackoverflow.com/questions/39270364/inserting-into-sql-server-varbinary-column-from-r-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!