使用计算在模式中存储新的永久 table
Store new permanent table in schema using compute
我想使用 dbplyr
语法对某些 table 执行一些 JOIN
/ FILTER
操作并将结果存储回数据库 没有先收集它。
根据我的阅读,compute(..., temporary = FALSE, ...)
应该这样做,但是我很难为我想要的 table 提供完全限定名称(即 database.schema.table_name
)商店
我知道 DBI::Id
和 dbplyr::in_schema
但我不知道如何正确使用它们。尝试使用 sql
至少做了我想要的(创建了 table)但导致了(spurios?)错误。
我需要做什么?
一些NoReprex
library(DBI)
library(dbplyr)
con <- dbConnect(odbc::odbc(), "myserver")
## do __not__ collect the data
my_frame <- con %>%
tbl(Id(catalog = "mydb", schema = "dbo", table = "mytable")) %>%
inner_join(con %>% tbl(Id(catalog = "mydb", schema = "dbo",
table = "yetanothertable")),
"id")
compute(my_frame,
# Id(catalog = "mydb", schema = "dbo", table = "mynewtable"), # (1)
# in_schema("dbo", "mynewtable"), # (2),
sql("mydb.dbo.mynewtable"), # (3)
FALSE)
根据我使用的变体,我得到不同的错误
# (1)
## Error in h(simpleError(msg, call)) :
## error in evaluating the argument 'conn' in selecting a method for function
## 'dbQuoteIdentifier': argument "con" is missing, with no default
# (2)
## Error in escape(x$schema, con = con) :
## argument "con" is missing, with no default
# (3)
## Error: nanodbc/nanodbc.cpp:1655: 42000: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near ')'.
## [Microsoft][SQL Server Native Client 11.0][SQL Server]Statement(s) could not be prepared.
## <SQL> 'SELECT *
## FROM (my.fully_qualified.name) "q02"
## WHERE (0 = 1)'
P.S.: 我真的希望能够用 fully 限定名称保存 table,包括数据库名称(虽然在这个简化的例子中是一样的)。所以 dbConnect(..., database = <somedb>)
不会解决我的问题 运行.
P.P.S:我正在寻找 compute
解决方案。我知道我可以自己构建 SQL
,但我真的很想知道我是否可以为此使用 dbplyr
抽象层。
我以前更喜欢涉及编写一些 SQL 的解决方案(根据 回答)。但是当你在你的问题中排除这种方法时,我测试并找到了一种不用写 SQL.
的方法
我们将使用 db_compute
而不是 compute
。
compute
的 documentation 声明“compute() 将结果存储在远程临时 table”。所以我认为这意味着我们不能使用 compute
. 编写永久 tables
-
db_compute
的 documentation 说得很少。但它出现在 db_copy_to
旁边,其目的与我们正在寻找的相似。所以值得一试(而且有效)。
常规设置
library(DBI)
library(dplyr)
library(dbplyr)
# connect to database
connection_string = "..."
db_connection = dbConnect(odbc::odbc(), .connection_string = connection_string)
# remote table
remote_table = tbl(db_connection, from = in_schema("schema","table"))
top_rows = remote_table %>%
head()
测试计算
top_rows %>% show_query()
# <SQL>
# SELECT TOP (6) *
# FROM [database_name].[schema_name].[table_name]
top_rows = top_rows %>%
compute()
# Created a temporary table named: #dbplyr_002
top_rows %>% show_query()
# <SQL>
# SELECT *
# FROM #dbplyr_.002
所以我们可以看到 compute
写了一个临时的 table。因此,如果我们做一些复杂的处理(而不是只取前几行),compute
将是存储处理后的 table 的有效方法,这样我们就可以避免每次查询时重复复杂的处理。
但是因为它是临时的,当我们与数据库断开连接时 table 应该消失:DBI::dbDisconnect(db_connection)
.
测试中db_compute
out = db_compute(
con = db_connection,
table = in_schema("schema","new_table"),
sql = sql_render(top_rows),
temporary = FALSE
)
out
# <IDENT> database_name.schema_name.new_table
# reconnect
new_remote_table = tbl(db_connection, from = in_schema("schema","new_table"))
所以我们现在可以从 R 中访问新的(永久的)table。我还通过 SQL 查询检查并确认 table 存在于数据库中。
注意由于db_compute
的文档很少,不清楚是否打算以这种方式使用。我已经测试了上面的内容并且它有效。但如果没有额外的文档,使用风险自负。
仅作记录,感谢 Simon 的回答,我终于找到了提供完全限定 table 名称(即包含数据库、架构和 table 名称)的正确方法。有了这条信息,一个人可以依靠 compute
,一切都像一个魅力。您只需提供数据库名称作为模式的一部分,并确保通过 sql
:
进行转义
compute(my_frame,
# in_schema("mydb.dbo", "mynewtable") would __not__ work
in_schema(sql("mydb.dbo"), "mynewtable"),
FALSE)
我想使用 dbplyr
语法对某些 table 执行一些 JOIN
/ FILTER
操作并将结果存储回数据库 没有先收集它。
根据我的阅读,compute(..., temporary = FALSE, ...)
应该这样做,但是我很难为我想要的 table 提供完全限定名称(即 database.schema.table_name
)商店
我知道 DBI::Id
和 dbplyr::in_schema
但我不知道如何正确使用它们。尝试使用 sql
至少做了我想要的(创建了 table)但导致了(spurios?)错误。
我需要做什么?
一些NoReprex
library(DBI)
library(dbplyr)
con <- dbConnect(odbc::odbc(), "myserver")
## do __not__ collect the data
my_frame <- con %>%
tbl(Id(catalog = "mydb", schema = "dbo", table = "mytable")) %>%
inner_join(con %>% tbl(Id(catalog = "mydb", schema = "dbo",
table = "yetanothertable")),
"id")
compute(my_frame,
# Id(catalog = "mydb", schema = "dbo", table = "mynewtable"), # (1)
# in_schema("dbo", "mynewtable"), # (2),
sql("mydb.dbo.mynewtable"), # (3)
FALSE)
根据我使用的变体,我得到不同的错误
# (1)
## Error in h(simpleError(msg, call)) :
## error in evaluating the argument 'conn' in selecting a method for function
## 'dbQuoteIdentifier': argument "con" is missing, with no default
# (2)
## Error in escape(x$schema, con = con) :
## argument "con" is missing, with no default
# (3)
## Error: nanodbc/nanodbc.cpp:1655: 42000: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near ')'.
## [Microsoft][SQL Server Native Client 11.0][SQL Server]Statement(s) could not be prepared.
## <SQL> 'SELECT *
## FROM (my.fully_qualified.name) "q02"
## WHERE (0 = 1)'
P.S.: 我真的希望能够用 fully 限定名称保存 table,包括数据库名称(虽然在这个简化的例子中是一样的)。所以 dbConnect(..., database = <somedb>)
不会解决我的问题 运行.
P.P.S:我正在寻找 compute
解决方案。我知道我可以自己构建 SQL
,但我真的很想知道我是否可以为此使用 dbplyr
抽象层。
我以前更喜欢涉及编写一些 SQL 的解决方案(根据
我们将使用 db_compute
而不是 compute
。
compute
的 documentation 声明“compute() 将结果存储在远程临时 table”。所以我认为这意味着我们不能使用compute
. 编写永久 tables
-
db_compute
的 documentation 说得很少。但它出现在db_copy_to
旁边,其目的与我们正在寻找的相似。所以值得一试(而且有效)。
常规设置
library(DBI)
library(dplyr)
library(dbplyr)
# connect to database
connection_string = "..."
db_connection = dbConnect(odbc::odbc(), .connection_string = connection_string)
# remote table
remote_table = tbl(db_connection, from = in_schema("schema","table"))
top_rows = remote_table %>%
head()
测试计算
top_rows %>% show_query()
# <SQL>
# SELECT TOP (6) *
# FROM [database_name].[schema_name].[table_name]
top_rows = top_rows %>%
compute()
# Created a temporary table named: #dbplyr_002
top_rows %>% show_query()
# <SQL>
# SELECT *
# FROM #dbplyr_.002
所以我们可以看到 compute
写了一个临时的 table。因此,如果我们做一些复杂的处理(而不是只取前几行),compute
将是存储处理后的 table 的有效方法,这样我们就可以避免每次查询时重复复杂的处理。
但是因为它是临时的,当我们与数据库断开连接时 table 应该消失:DBI::dbDisconnect(db_connection)
.
测试中db_compute
out = db_compute(
con = db_connection,
table = in_schema("schema","new_table"),
sql = sql_render(top_rows),
temporary = FALSE
)
out
# <IDENT> database_name.schema_name.new_table
# reconnect
new_remote_table = tbl(db_connection, from = in_schema("schema","new_table"))
所以我们现在可以从 R 中访问新的(永久的)table。我还通过 SQL 查询检查并确认 table 存在于数据库中。
注意由于db_compute
的文档很少,不清楚是否打算以这种方式使用。我已经测试了上面的内容并且它有效。但如果没有额外的文档,使用风险自负。
仅作记录,感谢 Simon 的回答,我终于找到了提供完全限定 table 名称(即包含数据库、架构和 table 名称)的正确方法。有了这条信息,一个人可以依靠 compute
,一切都像一个魅力。您只需提供数据库名称作为模式的一部分,并确保通过 sql
:
compute(my_frame,
# in_schema("mydb.dbo", "mynewtable") would __not__ work
in_schema(sql("mydb.dbo"), "mynewtable"),
FALSE)