2015-01-25 14 views
20

Tôi đang tìm nạp một nhóm các tập dữ liệu theo chương trình, nhiều trong số chúng có tên ngớ ngẩn bắt đầu bằng số và có các ký tự đặc biệt như dấu trừ trong chúng. Vì không có bộ dữ liệu nào đặc biệt lớn và tôi muốn lợi ích R đưa ra dự đoán tốt nhất về các kiểu dữ liệu, tôi (ab) sử dụng dplyr để kết xuất các bảng này vào trong SQLite.Tên bảng khung thoát bằng dplyr

Tôi đang sử dụng dấu ngoặc vuông để thoát khỏi tên bảng khủng khiếp, nhưng điều này dường như không hoạt động. Ví dụ:

data(iris) 
foo.db <- src_sqlite("foo.sqlite3", create = TRUE) 
copy_to(foo.db, df=iris, name="[14m3-n4m3]") 

Điều này dẫn đến các thông báo lỗi:

Error in sqliteSendQuery(conn, statement, bind.data) : error in statement: no such table: 14m3-n4m3

này hoạt động nếu tôi chọn một tên hợp lý. Tuy nhiên, vì nhiều lý do, tôi thực sự muốn giữ những cái tên cồng kềnh. Tôi cũng có thể tạo ra một bảng nặng tên như vậy trực tiếp từ sqlite:

sqlite> create table [14m3-n4m3](foo,bar,baz); 
sqlite> .tables 
14m3-n4m3 

Nếu không nứt thành điều quá sâu, điều này có vẻ như dplyr là xử lý các dấu ngoặc vuông trong một cách nào đó mà tôi không thể tìm ra. Nghi ngờ của tôi là đây là một lỗi, nhưng tôi muốn kiểm tra ở đây đầu tiên để chắc chắn rằng tôi đã không bỏ lỡ một cái gì đó.

EDIT: Tôi quên đề cập đến trường hợp tôi chỉ chuyển tên janky trực tiếp tới dplyr. Lỗi này như sau:

library(dplyr) 

data(iris) 
foo.db <- src_sqlite("foo.sqlite3", create = TRUE) 
copy_to(foo.db, df=iris, name="14M3-N4M3") 

Error in sqliteSendQuery(conn, statement, bind.data) : 
    error in statement: unrecognized token: "14M3" 
+4

Đây chỉ là phỏng đoán, nhưng có thể là do quy ước đặt tên của R. Một cách giải quyết khác mà tôi tìm thấy là sử dụng 'name = gsub (" [.] "," ", Make.names (" [14m3-n4m3] "))'. Nếu bạn đã làm điều đó bạn vẫn có thể truyền tên ban đầu của bạn trong 'copy_to()', mặc dù chúng sẽ hơi khác trong dữ liệu. Không chắc chắn nếu điều đó giúp nhưng đó là hai xu của tôi.Câu hỏi rất hay. –

+1

Đây là giải pháp tốt hơn so với những gì tôi đã bắt đầu xuống con đường thực hiện. Dần dần nói chuyện với chính mình vào ý tưởng rằng tên tốt + phức tạp khác> tên xấu. – Peter

+0

Tôi đồng ý với @RichardScriven - tốt hơn để sửa đổi tên với các công cụ hiện có hơn để cố gắng cuộn của riêng bạn! –

Trả lời

3

Đây là lỗi trong dplyr. Nó vẫn còn trong chủ github hiện tại. Như @hadley cho biết, anh ta đã cố gắng để thoát khỏi những thứ như tên bảng trong dplyr để ngăn chặn vấn đề này. Vấn đề hiện tại bạn đang gặp phải do thiếu thoát trong hai chức năng. Tạo bảng hoạt động tốt khi cung cấp tên bảng không thoát (và được thực hiện với dplyr::db_create_table). Tuy nhiên, việc chèn dữ liệu vào bảng được thực hiện bằng cách sử dụng DBI::dbWriteTable không hỗ trợ tên bảng lẻ. Nếu tên bảng được cung cấp cho hàm này được thoát, nó sẽ không tìm thấy nó trong danh sách các bảng (lỗi đầu tiên bạn báo cáo). Nếu nó được cung cấp thoát, thì SQL để thực hiện việc chèn không hợp lệ về mặt synatactically.

Vấn đề thứ hai xuất hiện khi bảng được cập nhật. Mã để lấy tên trường, lần này thực sự trong dplyr, lại không thoát khỏi tên bảng vì nó sử dụng paste0 thay vì build_sql.

Tôi đã sửa cả hai lỗi tại a fork of dplyr. Tôi cũng đã yêu cầu kéo đến @hadley và ghi chú về số phát hành https://github.com/hadley/dplyr/issues/926. Trong thời gian chờ đợi, nếu bạn muốn bạn có thể sử dụng devtools::install_github("NikNakk/dplyr", ref = "sqlite-escape") và sau đó hoàn nguyên về phiên bản chính khi nó đã được sửa.

Ngẫu nhiên, cách đúng SQL-99 để thoát khỏi tên bảng (và các số nhận dạng khác) trong SQL là với dấu ngoặc kép (xem SQL standard to escape column names?). MS Access sử dụng dấu ngoặc vuông, trong khi MySQL mặc định là backticks. dplyr sử dụng dấu ngoặc kép, theo tiêu chuẩn.

Cuối cùng, đề xuất từ ​​@RichardScriven sẽ không hoạt động phổ biến. Ví dụ: select là tên hợp lệ hoàn toàn trong R, nhưng không phải là tên bảng hợp lệ trong SQL. Điều tương tự cũng đúng đối với các từ dành riêng khác.

+0

Phát hành PR cho một lỗi lâu dài để trả lời câu hỏi - bravo! – Peter

+0

Nếu bạn đã rất nhanh chóng tải xuống phiên bản cố định của mình, tôi đã thực hiện một cam kết khác bổ sung thêm một dòng mã để xóa tài nguyên sau khi chèn. Bạn không chắc chắn mức độ quan trọng như thế nào, nhưng nó có vẻ hợp lý để làm và nằm trong bản gốc 'DBI :: dbWriteTable'. –

+2

Sau khi thảo luận với @hadley, bản sửa lỗi của tôi bây giờ là một lớp lót đơn giản hơn nhiều để khắc phục sự cố thứ hai được mô tả ở trên (thay thế 'dán0' bằng' build_sql'). Các thay đổi cần thiết đối với 'DBI :: dbWriteTable' đã được thực hiện trong [' RSQLite' trong phiên bản github] (https://github.com/rstats-db/RSQLite), mặc dù bạn cũng sẽ cần [phiên bản github của DBI] (https://github.com/rstats-db/DBI). –

Các vấn đề liên quan