Menu

ייבוא CSV ל-SQLite: טעינת נתונים עם .import והדגל --csv

איך מייבאים קובצי CSV ל-SQLite עם הפקודה .import: טיפול בכותרות, בטבלאות קיימות, במפרידים מותאמים ובשגיאות הנפוצות ביותר.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

ייבוא CSV נעשה ב-CLI, לא ב-SQL

אין פקודת IMPORT בניב ה-SQL של SQLite. טעינת CSV היא תכונה של מעטפת שורת הפקודה sqlite3: פקודת נקודה בשם .import. זה שינוי חשיבה חשוב אם אתם מגיעים מ-LOAD DATA INFILE של MySQL או מ-COPY של Postgres: אלה רצים בשרת, ואילו .import הוא משהו שכלי הלקוח עושה בשבילכם, קורא את הקובץ ומריץ פקודות INSERT מאחורי הקלעים.

לכן כל מה שבעמוד הזה מניח שאתם בתוך המעטפת sqlite3:

sqlite3 mydata.db

אם צריך לייבא מקוד אפליקציה, Python, Node או Go, תקראו את ה-CSV בשפה שלכם ותשתמשו בפקודות INSERT עם פרמטרים. נעסוק בגישה הזו בפרק על שילוב באפליקציות. כאן אנחנו מתמקדים ב-CLI.

ה-.import הבסיסי

הדרך הקצרה ביותר: אמרו ל-SQLite שהקובץ הוא CSV, ואז הפנו את .import לקובץ ולשם טבלה.

.mode csv
.import people.csv people

יש שתי אפשרויות, לפי השאלה אם people כבר קיימת:

  • הטבלה לא קיימת: SQLite יוצרת אותה ומשתמשת בשורה הראשונה של ה-CSV כשמות העמודות. כל עמודה מקבלת זיקת TEXT.
  • הטבלה קיימת: SQLite מכניסה כל שורה בקובץ כנתונים. שורת הכותרת, אם יש כזו, הופכת לשורה.

המקרה השני הוא המקום שבו רוב האנשים נכווים בניסיון הראשון. אם ל-CSV שלכם יש כותרת והטבלה כבר קיימת, צריך לדלג עליה במפורש.

דילוג על הכותרת בטבלה קיימת

השתמשו ב---skip 1 כדי לומר ל-.import להתעלם מ-N השורות הראשונות:

CREATE TABLE people (
    name TEXT,
    age  INTEGER,
    city TEXT
);

.import --csv --skip 1 people.csv people

--csv הוא קיצור של .mode csv שחל רק על הפקודה הזו, כך שלא צריך להגדיר את המצב בנפרד. --skip 1 משמיט את הכותרת. שאר השורות מוכנסות ל-people לפי סדר העמודות.

בדיקה מהירה אחרי הייבוא:

SELECT count(*) FROM people;
SELECT * FROM people LIMIT 5;

סדר העמודות בקובץ חייב להתאים לסדר העמודות בטבלה. אין מיפוי לפי כותרות: .import פשוט מתאים את השדה ה-N לעמודה ה-N.

לתת ל-SQLite ליצור את הטבלה בשבילכם

בעבודה חקרנית, הדרך הקלה ביותר היא לוותר לגמרי על CREATE TABLE ולתת ל-.import לבנות את הטבלה מהכותרת:

.mode csv
.import sales.csv sales

.schema sales

.schema sales יציג משהו כזה:

CREATE TABLE sales(
  "order_id" TEXT,
  "amount" TEXT,
  "ordered_at" TEXT
);

שימו לב שכל עמודה היא TEXT. זה מכוון: .import לא מנסה להסיק טיפוסים. אם אתם רוצים ש-amount תהיה מספר ממשי ו-ordered_at חותמת זמן תקינה, צרו קודם את הטבלה בעצמכם עם הטיפוסים הנכונים, ואז ייבאו עם --skip 1. זיקת הטיפוסים של SQLite תמיר מחרוזות מספריות למספרים שלמים וממשיים בזמן ההכנסה.

מפרידים מותאמים: TSV, קו אנכי, נקודה-פסיק

.mode csv משתמש בפסיק. לקבצים מופרדים בטאבים, החליפו מצב:

.mode tabs
.import data.tsv events

למפרידים אחרים, השתמשו ב-.separator אחרי בחירת מצב:

.mode csv
.separator "|"
.import pipe_data.txt events

דבר אחד שכדאי לדעת: .mode csv פועל לפי כללי המירכאות של RFC 4180, כך ששדות עם פסיקים או ירידות שורה מוטמעים עובדים, כל עוד הם עטופים כראוי ב-". .mode tabs הוא מצב פשוט יותר שמפצל לפי תו, בלי מירכאות. אם בקובץ שלכם יש שדות במירכאות עם מפרידים מוטמעים, הישארו ב-.mode csv ושנו את המפריד.

דוגמה מציאותית מההתחלה עד הסוף

נניח ש-orders.csv נראה כך:

order_id,customer,amount,ordered_at
1001,Ada,49.99,2026-01-12
1002,Boris,12.50,2026-01-13
1003,"Chen, Wei",199.00,2026-01-14

שימו לב שבשורה 3 יש פסיק בתוך שדה במירכאות. הנה הסשן המלא:

במעטפת אמיתית, בלוק ה-INSERT היה מוחלף בפקודה אחת: .import --csv --skip 1 orders.csv orders. השדה "Chen, Wei" נשאר שלם כי מצב CSV מכבד את המירכאות. amount נשמרת כמספר ממשי ו-order_id כמספר שלם, בזכות טיפוסי העמודות.

לעטוף את הייבוא בטרנזקציה

.import מריץ INSERT אחד לכל שורה. לכמה אלפי שורות זה בסדר. למיליון שורות זה איטי עד כאב, אלא אם עוטפים את הכול בטרנזקציה כדי ש-SQLite לא תבצע commit אחרי כל שורה:

BEGIN;
.import --csv --skip 1 big_file.csv events
COMMIT;

השינוי היחיד הזה יכול להפוך ייבוא של כמה דקות לכמה שניות. אם משהו נכשל באמצע הייבוא, ROLLBACK מבטל את הטעינה החלקית, וזה גם נוח לניסיונות חוזרים.

אפשר להאיץ עוד יותר אם מוחקים אינדקסים לפני הייבוא ויוצרים אותם מחדש אחריו: תחזוקת אינדקסים לכל שורה מצטברת.

שגיאות נפוצות ואיך מתקנים אותן

Error: expected N columns but found M: מספר השדות בשורה לא תואם לטבלה. בדרך כלל:

  • פסיק תועה בשדה שאינו במירכאות. ייצאו מחדש עם מירכאות CSV תקינות, או עברו ל-.mode csv (RFC 4180) במקום .mode tabs.
  • שורה ריקה בסוף הקובץ. ערכו את הקובץ או השתמשו ב---skip באופן יצירתי.
  • בטבלה יש יותר עמודות מאשר ב-CSV. הוסיפו לקובץ את העמודות החסרות, או הכניסו לטבלת ביניים במבנה הנכון והעתיקו משם לטבלה האמיתית.

שורת הכותרת מופיעה כנתונים: שכחתם --skip 1 בטבלה קיימת. מחקו את השורה (DELETE FROM t WHERE rowid = 1) והריצו שוב עם הדגל.

מספרים נשמרים כמחרוזות: נתתם ל-.import ליצור את הטבלה, ולכן כל עמודה היא TEXT. מחקו את הטבלה, הגדירו אותה במפורש עם עמודות INTEGER/REAL וייבאו מחדש.

Error: no such file: הנתיב יחסי למקום שממנו הפעלתם את sqlite3, לא לקובץ מסד הנתונים. השתמשו בנתיב מוחלט או עשו cd לתיקייה הנכונה לפני פתיחת המעטפת.

ה-CLI מדפיס מספרי שורות בשגיאות, וזו הדרך המהירה ביותר למצוא את השורה הבעייתית בקובץ גדול.

סיכום מהיר

  • .import היא פקודת נקודה של ה-CLI, לא SQL. הריצו אותה בתוך המעטפת sqlite3.
  • השתמשו ב---csv כדי לטפל במירכאות כראוי, וב---skip 1 כדי להתעלם משורת כותרת.
  • אם הטבלה לא קיימת, .import יוצר אותה מהכותרת, אבל כל עמודה תהיה TEXT. צרו את הטבלה בעצמכם כדי לקבל טיפוסים נכונים.
  • עטפו ייבוא גדול ב-BEGIN/COMMIT כדי להימנע מטרנזקציה נפרדת לכל שורה.
  • סדר העמודות בקובץ חייב להתאים לסדר העמודות בטבלה.

הצעד הבא: ייצוא הנתונים החוצה

ייבוא הוא רק חצי מהסיפור. אותה מעטפת יכולה לייצא תוצאות שאילתה או טבלאות שלמות חזרה ל-CSV, ל-JSON או ל-SQL: שימושי לגיבויים, לצינורות נתונים ולהעברת נתונים לכלים אחרים. על זה בעמוד על ייצוא נתונים.

שאלות נפוצות

איך מייבאים קובץ CSV ל-SQLite?

פתחו את מסד הנתונים עם ה-CLI של sqlite3, עברו למצב CSV עם .mode csv, ואז הריצו .import data.csv table_name. אם הטבלה עוד לא קיימת, SQLite יוצרת אותה ומשתמשת בשורה הראשונה של הקובץ כשמות העמודות. אם היא קיימת, כל שורה בקובץ מוכנסת כנתונים, ולכן בדרך כלל תרצו .import --skip 1 כדי לדלג על הכותרת.

איך מייבאים CSV עם שורת כותרת לטבלת SQLite קיימת?

השתמשו ב-.import --csv --skip 1 data.csv table_name. הדגל --skip 1 אומר ל-SQLite להתעלם מהשורה הראשונה כדי ששורת הכותרת לא תהפוך לשורת נתונים. בלעדיו תקבלו שורה שמכילה את שמות העמודות עצמם.

למה ייבוא CSV ב-SQLite נכשל עם 'expected N columns but found M'?

בקובץ יש שורות עם מספר עמודות שונה מזה של הטבלה, בדרך כלל בגלל פסיקים מוטמעים, מירכאות שלא עברו escape או שורה ריקה בסוף. השתמשו ב-.mode csv (או ב---csv) במקום ב-.mode tabs כדי ש-SQLite תטפל במירכאות לפי RFC 4180, ובדקו את הקובץ בעורך טקסט כדי למצוא מפרידים תועים. ה-CLI מדפיס את מספר השורה הבעייתית, וזו הדרך המהירה ביותר למצוא אותה.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל