如何使用 RODBC 将数据帧保存到 table,并在数据库中生成主键
How to use RODBC to save dataframe to table with primary key generated at database
我想使用 R 脚本将数据框输入数据库中现有的 table,并且我希望数据库中的 table 具有顺序主键。我的问题是 RODBC 似乎不允许主键约束。
这里是 SQL,用于创建我想要的 table:
CREATE TABLE [dbo].[results] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[FirstName] VARCHAR (255) NULL,
[LastName] VARCHAR (255) NULL,
[Birthday] DATETIME NULL,
[CreateDate] DATETIME NULL,
CONSTRAINT [PK_dbo.results] PRIMARY KEY CLUSTERED ([ID] ASC)
);
并使用一些 R 代码进行测试:
ConnectionString1="Driver=ODBC Driver 11 for SQL Server;Server=myserver; Database=TestDb; trusted_connection=yes"
ConnectionString2="Driver=ODBC Driver 11 for SQL Server;Server=notmyserver; Database=TestDb; trusted_connection=yes"
db1=odbcDriverConnect(ConnectionString1)
query="SELECT a.[firstname] as FirstName
, a.[lastname] as LastName
, Cast(a.[dob] as datetime) as Birthday
, cast(a.createDate as datetime) as CreateDate
FROM [dbo].[People] a"
results=NULL
results=sqlQuery(db1,query,stringsAsFactors=FALSE)
close(db1)
db2=odbcDriverConnect(ConnectionString)
sqlSave(db2,
results,
append = TRUE,
varTypes=c(Birthday="datetime", CreateDate="datetime"),
colnames = FALSE,
rownames = FALSE,fast=FALSE)
close(db2)
R 代码的第一部分只是将一些测试数据放入数据框中——它工作正常,这不是我这里的问题的一部分(我只是把它包括在这里,这样你就可以看到测试的格式是什么数据是)。当我 运行 sqlSave
函数时,我收到一条错误消息:
Error in dimnames(x) <- dn :
length of 'dimnames' [2] not equal to array extent
但是,如果我从数据库中删除主键,一切正常 table:
CREATE TABLE [dbo].[results] (
[FirstName] VARCHAR (255) NULL,
[LastName] VARCHAR (255) NULL,
[Birthday] DATETIME NULL,
[CreateDate] DATETIME NULL
);
显然主键是问题所在。通常使用 entity framework 或其他(据我了解),主键是在您输入数据时在数据库中创建的。
我想要一种仅使用 R 脚本将数据附加到具有主键的 table 的方法。那可能吗?我要添加的 table 中可能已经有数据,所以在尝试附加到 table.
之前,我真的看不到在 R 中创建密钥的方法
问题出在 http://github.com/cran/RODBC/blob/master/R/sql.R 中的第 361 行 - data.frame 和数据库 table 的列数必须完全相同,否则您会在堆栈跟踪中遇到此错误:
Error in dimnames(x) <- dn :
length of 'dimnames' [2] not equal to array extent
3. `colnames<-`(`*tmp*`, value = c("ID", "FirstName", "LastName",
"Birthday", "CreateDate")) at sql.R#361
2. sqlwrite(channel, tablename, dat, verbose = verbose, fast = fast,
test = test, nastring = nastring) at sql.R#211
1. sqlSave(db2, results, append = TRUE, varTypes = c(Birthday = "datetime",
CreateDate = "datetime"), colnames = FALSE, rownames = FALSE,
fast = FALSE, verbose = TRUE)
如果您将 ID 列添加到 data.frame
,您将无法再使用 autoinc
ID 列,因此这不是解决方案(或解决方法)。
"simple" RODBC::sqlSave
的 "same columns" 限制的解决方法是:
- 使用
sqlSave
将新行保存到另一个table名称
- 通过
RODBC::sqlQuery
发送 insert into ... select from ...
以将新行附加到包含 autoinc ID 的原始 table
专栏
- 再次删除包含新行的 table (
drop table...
)
更好的选择是使用新的 odbc
包,它还通过类似批量插入的方式提供更好的性能,而不是像 RODBC
那样发送单个 insert
语句:
查找函数 dbWriteTable
(它是接口 DBI::dbWriteTable
的一个实现)。
我想使用 R 脚本将数据框输入数据库中现有的 table,并且我希望数据库中的 table 具有顺序主键。我的问题是 RODBC 似乎不允许主键约束。
这里是 SQL,用于创建我想要的 table:
CREATE TABLE [dbo].[results] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[FirstName] VARCHAR (255) NULL,
[LastName] VARCHAR (255) NULL,
[Birthday] DATETIME NULL,
[CreateDate] DATETIME NULL,
CONSTRAINT [PK_dbo.results] PRIMARY KEY CLUSTERED ([ID] ASC)
);
并使用一些 R 代码进行测试:
ConnectionString1="Driver=ODBC Driver 11 for SQL Server;Server=myserver; Database=TestDb; trusted_connection=yes"
ConnectionString2="Driver=ODBC Driver 11 for SQL Server;Server=notmyserver; Database=TestDb; trusted_connection=yes"
db1=odbcDriverConnect(ConnectionString1)
query="SELECT a.[firstname] as FirstName
, a.[lastname] as LastName
, Cast(a.[dob] as datetime) as Birthday
, cast(a.createDate as datetime) as CreateDate
FROM [dbo].[People] a"
results=NULL
results=sqlQuery(db1,query,stringsAsFactors=FALSE)
close(db1)
db2=odbcDriverConnect(ConnectionString)
sqlSave(db2,
results,
append = TRUE,
varTypes=c(Birthday="datetime", CreateDate="datetime"),
colnames = FALSE,
rownames = FALSE,fast=FALSE)
close(db2)
R 代码的第一部分只是将一些测试数据放入数据框中——它工作正常,这不是我这里的问题的一部分(我只是把它包括在这里,这样你就可以看到测试的格式是什么数据是)。当我 运行 sqlSave
函数时,我收到一条错误消息:
Error in dimnames(x) <- dn : length of 'dimnames' [2] not equal to array extent
但是,如果我从数据库中删除主键,一切正常 table:
CREATE TABLE [dbo].[results] (
[FirstName] VARCHAR (255) NULL,
[LastName] VARCHAR (255) NULL,
[Birthday] DATETIME NULL,
[CreateDate] DATETIME NULL
);
显然主键是问题所在。通常使用 entity framework 或其他(据我了解),主键是在您输入数据时在数据库中创建的。
我想要一种仅使用 R 脚本将数据附加到具有主键的 table 的方法。那可能吗?我要添加的 table 中可能已经有数据,所以在尝试附加到 table.
之前,我真的看不到在 R 中创建密钥的方法问题出在 http://github.com/cran/RODBC/blob/master/R/sql.R 中的第 361 行 - data.frame 和数据库 table 的列数必须完全相同,否则您会在堆栈跟踪中遇到此错误:
Error in dimnames(x) <- dn :
length of 'dimnames' [2] not equal to array extent
3. `colnames<-`(`*tmp*`, value = c("ID", "FirstName", "LastName",
"Birthday", "CreateDate")) at sql.R#361
2. sqlwrite(channel, tablename, dat, verbose = verbose, fast = fast,
test = test, nastring = nastring) at sql.R#211
1. sqlSave(db2, results, append = TRUE, varTypes = c(Birthday = "datetime",
CreateDate = "datetime"), colnames = FALSE, rownames = FALSE,
fast = FALSE, verbose = TRUE)
如果您将 ID 列添加到 data.frame
,您将无法再使用 autoinc
ID 列,因此这不是解决方案(或解决方法)。
"simple" RODBC::sqlSave
的 "same columns" 限制的解决方法是:
- 使用
sqlSave
将新行保存到另一个table名称 - 通过
RODBC::sqlQuery
发送insert into ... select from ...
以将新行附加到包含 autoinc ID 的原始 table 专栏 - 再次删除包含新行的 table (
drop table...
)
更好的选择是使用新的 odbc
包,它还通过类似批量插入的方式提供更好的性能,而不是像 RODBC
那样发送单个 insert
语句:
查找函数 dbWriteTable
(它是接口 DBI::dbWriteTable
的一个实现)。