2017-11-24 17 views
5

gì tôi muốn là để chèn dữ liệu trong bảng mysql nhưng tôi không thể tìm ra cách để làm cho mối quan hệ từ một hànglàm thế nào để chèn tab tập tin được phân định vào mysql với mối quan hệ

giả sử tôi có một tập tin file.tab nó chứa dữ liệu trong như

parent_1 parent_details_1 child_1.1 child_details_1.1 child_1.2 child_details_1.2 
parent_2 parent_details_2 child_2.1 child_details_2.1 
parent_3 parent_details_3 child_3.1 child_details_3.1 child_3.2 child_details_3.2 child_3.3 child_details_3.3 

những gì tôi muốn đạt được là để chèn dữ liệu trong hai bảng như

  parent_table 
+---+-----------+-------------------+ 
|id | name |  details  | 
+---+-----------+-------------------+ 
| 1 | parent_1 | parent_details_1 | 
| 2 | parent_2 | parent_details_2 | 
| 3 | parent_3 | parent_details_3 | 
+---+-----------+-------------------+ 


       child_table 
+---+-----+-----------+-------------------+ 
|id | pid | name |  details  | 
+---+-----+-----------+-------------------+ 
| 1 | 1 | child_1.1 | child_details_1.1 | 
| 2 | 1 | child_1.2 | child_details_1.2 | 
| 3 | 2 | child_2.1 | child_details_2.1 | 
| 4 | 3 | child_3.1 | child_details_3.1 | 
| 5 | 3 | child_3.2 | child_details_3.2 | 
| 6 | 3 | child_3.3 | child_details_3.3 | 
+---+-----+-----------+-------------------+ 

hai cột đầu tiên là dành cho cha mẹ và sau đó hai cột hai thuộc về con nhưng tôi không biết có bao nhiêu con của bố mẹ.

tôi đã cố gắng tải tệp theo cách đó.

LOAD DATA INFILE '/tmp/file.tab INTO TABLE ... 

nhưng tôi làm gì tiếp theo mà tôi không biết.

vì vậy vui lòng giúp tôi trong câu hỏi này.

Trả lời

6

Tạo bảng (Staging) với nhiều cột. Có các cột trống (NULL) cho parent_id và id cho trẻ em.

Hy vọng rằng các dòng 'ngắn' sẽ đặt null vào cột thiếu trẻ em trong số LOAD DATA.

INSERT .. SELECT .. để nhận số parentparent_detail vào bảng Parents. Kéo lại số ids từ Parents vào Staging.parent_id. Các chi tiết về hai SQLs cho đây là trong http://mysql.rjweb.org/doc.php/staging_table#normalization

Bây giờ làm điều gì đó tương tự cho mỗi "đứa trẻ" có thể tập hợp các cột: child1child1_detail (có thể là NULL cặp) và hiện NULL child1_id. Ditto cho child2 *, vv Lưu ý rằng khi điền bảng Children, bạn đã có sẵn parent_id.

Đây là cách tất cả-SQL để thực hiện tác vụ. Nó chỉ hơi lộn xộn hơn viết Perl/PHP/Java/VB/bất kỳ mã nào để thực hiện tác vụ.

+0

Như @RickJames nói trong câu cuối cùng, đó là một cách toàn SQL đó là hơi ít lộn xộn. Tôi nghĩ rằng bạn nên làm một số loại bình thường hóa bên ngoài của SQL mà sẽ được khá dễ dàng. Bạn có thể sử dụng một tìm kiếm đơn giản, nơi một dòng mới được thêm vào sau mỗi 2 TABS. Sau đó, bạn có thể grep cho 'parent' hoặc' child' (giả sử bạn có một số cách để định danh ID 2) để bạn biết có nên 'INSERT' vào bảng' parent' hoặc 'child' hay không. IMHO, nó dường như không có giá trị làm tất cả trong 1 ngôn ngữ, especiall nếu tập tin là như thường xuyên như bạn hiển thị (mỗi 2 TABS là một mục mới). –

1

Giả sử cả trẻ em và cha mẹ là một người tôi chỉ tạo bảng Person với id_parent là tùy chọn.

CREATE TABLE person (
    id int(11) NOT NULL AUTO_INCREMENT, 
    name varchar(50) DEFAULT NULL, 
    details varchar(255) DEFAULT NULL, 
    id_parent1 int(11) DEFAULT NULL, 
    id_parent2 int(11) DEFAULT NULL, 
    PRIMARY KEY (id) 
); 

Cách bạn tải dữ liệu phụ thuộc rất nhiều vào ngôn ngữ yêu thích của bạn. Load data infile yêu cầu bảng kết quả tĩnh.

Số hàng bạn có thể khác nhau và bạn sẽ cần nhập khá nhiều hàng vào một cột. Sau đó, bạn có thể sử dụng một thủ tục được lưu trữ để lặp qua nó:

  • Nhìn vào cursors để xem cách lặp qua từng hàng của bảng dàn một cột như vậy.
  • Sử dụng replace trên dấu phân cách tab, bạn có thể tìm ra số cột trong mỗi hàng.
  • Sử dụng vòng lặp while, sau đó bạn có thể bắt đầu nhập trẻ em trước và sau đó là cha mẹ.

Trong tất cả sự công bằng, đây sẽ là một thủ tục lưu trữ khá phức tạp và cho người mới bắt đầu có thể khá khó viết. Nếu bạn đã quen thuộc với bất kỳ ngôn ngữ lập trình và phương tiện kết nối với MySQL, bạn có thể làm điều này một cách thanh lịch hơn nhiều.

0

Nếu giải pháp không cần phải là tất cả trong SQL, tôi thấy rằng tiền xử lý thường đơn giản hơn. Trong trường hợp này, chia dữ liệu thành hai tệp có thể được tải một cách trivially với LOAD DATA INFILE (một cho bảng cha và một cho bảng con).

Dưới đây là một cách để làm tiền xử lý sử dụng perl

my ($parent_id, $child_id) = (0, 0); 
my (@parent_table, @child_table); 
while (<>) {     # for each line of input 
    chomp; 
    # split on tabs 
    my ($parent_name, $parent_detail, @child_id_detail_pairs) = split /\t/; 
    # create a row and parent_id for the parent table 
    push @parent_table, [ ++$parent_id, $parent_name, $parent_detail ]; 

    while (@child_id_detail_pairs) { # while we have child names & details 
    # remove a name and details 
    my $child_name = shift @child_id_detail_pairs; 
    my $child_details = shift @child_id_detail_pairs; 

    # create a row and child_id for the child table 
    push @child_table, [ ++$child_id, $parent_id, $child_name, $child_details ]; 
    } 
} 

# write this to one file to load into the parent table 
print "parent_table\n"; 
for my $row (@parent_table) { 
    print join("\t", @$row), "\n"; 
} 

# write this to one file to load into the child table 
print "child_table\n"; 
for my $row (@child_table) { 
    print join("\t", @$row), "\n"; 
} 
+0

tệp có kích thước rất lớn khoảng 20 đến 25 GB không xử lý hoặc không mất nhiều thời gian. – User97798

+0

@ User97798 như văn bản này đặt toàn bộ tập tin trong bộ nhớ trước khi in. Tùy thuộc vào số lượng bộ nhớ bạn có mà có thể không lý tưởng. Tuy nhiên, kịch bản có thể dễ dàng được sửa đổi để xuất một hàng tại một thời điểm. Sau đó, bộ nhớ sẽ không là vấn đề. Điều này nên được thực hiện hợp lý, ít nhất là cho một lần. Ngay cả khi bạn làm điều đó thường xuyên tôi sẽ kiểm tra nó và chỉ tối ưu hóa nếu cần thiết. –

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