เป็นไปได้ที่จะทำ MySQL foreign key ให้กับหนึ่งในสองตารางที่เป็นไปได้หรือไม่?


180

นี่คือปัญหาของฉันฉันมีสามตาราง ภูมิภาคประเทศรัฐ ประเทศสามารถอยู่ภายในภูมิภาครัฐสามารถอยู่ในภูมิภาค ภูมิภาคคือสุดยอดห่วงโซ่อาหาร

ตอนนี้ฉันกำลังเพิ่มตาราง popular_areas ที่มีสองคอลัมน์ region_id และ popular_place_id เป็นไปได้ไหมที่จะทำให้ popular_place_id เป็นกุญแจสำคัญในต่างประเทศหรือทั้งสองรัฐ ฉันอาจจะต้องเพิ่มคอลัมน์ popular_place_type เพื่อกำหนดว่า id อธิบายประเทศหรือรัฐด้วยวิธีใด

คำตอบ:


282

สิ่งที่คุณกำลังอธิบายเรียกว่าสมาคมโพลีมอร์ฟิค นั่นคือคอลัมน์ "foreign key" มีค่า id ที่ต้องมีอยู่ในหนึ่งในชุดของตารางเป้าหมาย โดยทั่วไปแล้วตารางเป้าหมายจะเกี่ยวข้องกันในบางวิธีเช่นเป็นอินสแตนซ์ของซูเปอร์คลาสทั่วไปของข้อมูล คุณต้องการคอลัมน์อื่นที่อยู่ด้านข้างคอลัมน์คีย์ต่างประเทศเพื่อให้ในแต่ละแถวคุณสามารถกำหนดตารางเป้าหมายที่อ้างอิงได้

CREATE TABLE popular_places (
  user_id INT NOT NULL,
  place_id INT NOT NULL,
  place_type VARCHAR(10) -- either 'states' or 'countries'
  -- foreign key is not possible
);

ไม่มีวิธีใดในการสร้างแบบจำลอง Polymorphic Associations โดยใช้ข้อ จำกัด ของ SQL ข้อ จำกัด foreign key อ้างอิงตารางเป้าหมายหนึ่งตารางเสมอ

Polymorphic Association ได้รับการสนับสนุนโดยเฟรมเวิร์กเช่น Rails และ Hibernate แต่พวกเขาบอกอย่างชัดเจนว่าคุณต้องปิดการใช้งานข้อ จำกัด ของ SQL เพื่อใช้คุณสมบัตินี้ แอปพลิเคชันหรือกรอบงานจะต้องทำงานเทียบเท่าเพื่อให้มั่นใจว่าการอ้างอิงนั้นเป็นที่น่าพอใจ นั่นคือค่าใน foreign key มีอยู่ในหนึ่งในตารางเป้าหมายที่เป็นไปได้

Polymorphic Associations นั้นอ่อนแอเมื่อเทียบกับการบังคับใช้ความสอดคล้องของฐานข้อมูล ความถูกต้องของข้อมูลขึ้นอยู่กับไคลเอนต์ทั้งหมดที่เข้าถึงฐานข้อมูลด้วยตรรกะความสมบูรณ์ของ Referential เดียวกันที่บังคับใช้และการบังคับใช้ต้องปราศจากข้อบกพร่อง

ต่อไปนี้เป็นโซลูชันทางเลือกบางตัวที่ใช้ประโยชน์จาก integrity Referential ที่บังคับใช้ฐานข้อมูล:

สร้างตารางพิเศษหนึ่งตารางต่อเป้าหมาย ตัวอย่างเช่นpopular_statesและpopular_countriesซึ่งการอ้างอิงstatesและcountriesตามลำดับ แต่ละตาราง "ยอดนิยม" เหล่านี้ยังอ้างอิงโปรไฟล์ของผู้ใช้

CREATE TABLE popular_states (
  state_id INT NOT NULL,
  user_id  INT NOT NULL,
  PRIMARY KEY(state_id, user_id),
  FOREIGN KEY (state_id) REFERENCES states(state_id),
  FOREIGN KEY (user_id) REFERENCES users(user_id),
);

CREATE TABLE popular_countries (
  country_id INT NOT NULL,
  user_id    INT NOT NULL,
  PRIMARY KEY(country_id, user_id),
  FOREIGN KEY (country_id) REFERENCES countries(country_id),
  FOREIGN KEY (user_id) REFERENCES users(user_id),
);

นี่หมายความว่าการรับสถานที่โปรดยอดนิยมของผู้ใช้ทั้งหมดคุณต้องสอบถามทั้งสองตารางนี้ แต่หมายความว่าคุณสามารถพึ่งพาฐานข้อมูลเพื่อบังคับใช้ความสอดคล้อง

สร้างplacesตารางเป็น supertable ในฐานะที่เป็นแอบี้กล่าวเป็นทางเลือกที่สองคือการที่ได้รับความนิยมของสถานที่อ้างอิงตารางเช่นplacesซึ่งเป็นผู้ปกครองทั้งสองและstates countriesนั่นคือทั้งรัฐและประเทศยังมีความสำคัญต่างประเทศไปplaces(คุณยังสามารถทำให้ต่างประเทศที่สำคัญนี้ยังเป็นคีย์หลักของstatesและcountries)

CREATE TABLE popular_areas (
  user_id INT NOT NULL,
  place_id INT NOT NULL,
  PRIMARY KEY (user_id, place_id),
  FOREIGN KEY (place_id) REFERENCES places(place_id)
);

CREATE TABLE states (
  state_id INT NOT NULL PRIMARY KEY,
  FOREIGN KEY (state_id) REFERENCES places(place_id)
);

CREATE TABLE countries (
  country_id INT NOT NULL PRIMARY KEY,
  FOREIGN KEY (country_id) REFERENCES places(place_id)
);

ใช้สองคอลัมน์ แทนที่จะเป็นหนึ่งคอลัมน์ที่อาจอ้างอิงหนึ่งในสองตารางเป้าหมายให้ใช้สองคอลัมน์ สองคอลัมน์นี้อาจเป็นNULL ; NULLในความเป็นจริงเพียงหนึ่งของพวกเขาควรจะไม่ใช่

CREATE TABLE popular_areas (
  place_id SERIAL PRIMARY KEY,
  user_id INT NOT NULL,
  state_id INT,
  country_id INT,
  CONSTRAINT UNIQUE (user_id, state_id, country_id), -- UNIQUE permits NULLs
  CONSTRAINT CHECK (state_id IS NOT NULL OR country_id IS NOT NULL),
  FOREIGN KEY (state_id) REFERENCES places(place_id),
  FOREIGN KEY (country_id) REFERENCES places(place_id)
);

ในแง่ของทฤษฎีเชิงสัมพันธ์สมาคมโพลีมอร์ฟิคละเมิดรูปแบบปกติครั้งแรกเพราะpopular_place_idคอลัมน์มีผลกับความหมายสองประการนั่นคือเป็นรัฐหรือประเทศ คุณจะไม่เก็บบุคคลageและบุคคลphone_numberในคอลัมน์เดียวและด้วยเหตุผลเดียวกับที่คุณไม่ควรจัดเก็บทั้งสองstate_idและcountry_idในคอลัมน์เดียว ความจริงที่ว่าแอตทริบิวต์ทั้งสองนี้มีชนิดข้อมูลที่เข้ากันได้นั้นเป็นเรื่องบังเอิญ พวกเขายังคงมีความหมายที่แตกต่างกันนิติบุคคล

สมาคม Polymorphic ก็ละเมิดเช่นกัน ฟอร์มปกติที่สามด้วยเนื่องจากความหมายของคอลัมน์ขึ้นอยู่กับคอลัมน์พิเศษที่กำหนดชื่อตารางซึ่งคีย์ต่างประเทศอ้างอิง ในฟอร์มปกติที่สามแอตทริบิวต์ในตารางจะต้องขึ้นอยู่กับคีย์หลักของตารางนั้นเท่านั้น


ความคิดเห็นอีกครั้งจาก @SavasVedova:

ฉันไม่แน่ใจว่าฉันทำตามคำอธิบายของคุณโดยไม่เห็นคำจำกัดความของตารางหรือแบบสอบถามตัวอย่าง แต่ดูเหมือนว่าคุณมีหลายFiltersตารางโดยแต่ละอันมีคีย์ต่างประเทศที่อ้างอิงถึงProductsตารางกลาง

CREATE TABLE Products (
  product_id INT PRIMARY KEY
);

CREATE TABLE FiltersType1 (
  filter_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

CREATE TABLE FiltersType2 (
  filter_id INT  PRIMARY KEY,
  product_id INT NOT NULL,
  FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

...and other filter tables...

การเข้าร่วมผลิตภัณฑ์กับตัวกรองประเภทใดประเภทหนึ่งนั้นเป็นเรื่องง่ายถ้าคุณรู้ว่าคุณต้องการเข้าร่วมประเภทใด:

SELECT * FROM Products
INNER JOIN FiltersType2 USING (product_id)

ถ้าคุณต้องการให้ตัวกรองเป็นแบบไดนามิกคุณต้องเขียนรหัสแอปพลิเคชันเพื่อสร้างแบบสอบถาม SQL SQL ต้องการให้ระบุตารางและแก้ไขในเวลาที่คุณเขียนแบบสอบถาม คุณไม่สามารถเลือกตารางที่เข้าร่วมได้แบบไดนามิกโดยยึดตามค่าที่พบในแต่ละแถวของProductsคุณไม่สามารถทำให้ตารางเข้าร่วมจะได้รับเลือกแบบไดนามิกขึ้นอยู่กับค่าที่พบในแต่ละแถวของ

ตัวเลือกอื่น ๆ เท่านั้นคือการเข้าร่วมกับตารางตัวกรองทั้งหมดโดยใช้การรวมภายนอก ผู้ที่ไม่มี product_id ที่ตรงกันจะถูกส่งคืนเป็น null แถวเดียว แต่คุณยังคงต้องฮาร์ดโค้ดตารางที่เข้าร่วมทั้งหมดและหากคุณเพิ่มตารางตัวกรองใหม่คุณต้องอัปเดตรหัสของคุณ

SELECT * FROM Products
LEFT OUTER JOIN FiltersType1 USING (product_id)
LEFT OUTER JOIN FiltersType2 USING (product_id)
LEFT OUTER JOIN FiltersType3 USING (product_id)
...

อีกวิธีในการเข้าร่วมกับตารางตัวกรองทั้งหมดคือการทำมันตามลำดับ:

SELECT * FROM Product
INNER JOIN FiltersType1 USING (product_id)
UNION ALL
SELECT * FROM Products
INNER JOIN FiltersType2 USING (product_id)
UNION ALL
SELECT * FROM Products
INNER JOIN FiltersType3 USING (product_id)
...

แต่รูปแบบนี้ยังต้องการให้คุณเขียนการอ้างอิงไปยังตารางทั้งหมด ไม่มีการรับรอบที่


คุณจะแนะนำบิลแบบไหน ฉันอยู่ระหว่างการออกแบบฐานข้อมูล แต่ฉันเสียไป โดยทั่วไปฉันจำเป็นต้องเชื่อมโยงตัวกรองกับผลิตภัณฑ์และค่าของตัวกรองจะถูกเติมผ่านตารางที่แตกต่าง แต่ปัญหาคือตัวกรองจะถูกสร้างโดยผู้ดูแลระบบดังนั้นข้อมูลอาจแตกต่างกันไปขึ้นอยู่กับประเภทของตัวกรองดังนั้นjoinเป้าหมายจะเปลี่ยนแปลงเช่นกัน ...... ฉันยุ่งมากเกินไปหรือเปล่า? ช่วยด้วย!
Savas Vedova

+1 ขอบคุณสำหรับคำตอบที่ยอดเยี่ยม คำถามหนึ่งที่ฉันมีกับวิธีแก้ปัญหาแรก / วินาทีคือ: มีการละเมิดมาตรฐานกับข้อเท็จจริงที่ว่าหลายตารางสามารถอ้างถึงคีย์หลักเดียวกันใน meta-table นั้นได้หรือไม่ ฉันรู้ว่าคุณสามารถแก้ปัญหานี้ด้วยตรรกะ แต่ฉันไม่เห็นวิธีใด ๆ สำหรับฐานข้อมูลในการบังคับใช้ยกเว้นว่าฉันทำอะไรหายไป
Rob

5
ฉันชอบวิธีการกับ "CONSTRAINT CHECK" แต่มันสามารถปรับปรุงได้ถ้าเราเปลี่ยน "OR" เป็น "XOR" ด้วยวิธีนี้เรารับประกันว่าคอลัมน์เดียวจากชุดจะไม่เป็นโมฆะ
alex_b

1
@alex_b ใช่แล้วเป็นเรื่องที่ดี แต่ XOR แบบลอจิคัลไม่ได้เป็น SQL มาตรฐานและไม่รองรับโดยยี่ห้อ SQL ทั้งหมด MySQL มี แต่ PostgreSQL ไม่ Oracle มี แต่ Microsoft ไม่ได้จนถึงปี 2016 เป็นต้น
Bill Karwin

1
"คอลัมน์ทั้งสองนี้อาจเป็นค่า NULL อันที่จริงมีเพียงหนึ่งคอลัมน์เท่านั้นที่ไม่เป็นค่า NULL" - นี่จะเป็นการละเมิด 1NF!
onedaywhen

10

นี่ไม่ใช่ทางออกที่หรูหราที่สุดในโลก แต่คุณสามารถใช้การสืบทอดตารางที่เป็นรูปธรรมได้เพื่อทำให้งานนี้

แนวความคิดคุณกำลังเสนอแนวคิดเกี่ยวกับคลาสของ "สิ่งต่าง ๆ ที่สามารถเป็นที่นิยมในพื้นที่" ซึ่งสถานที่ทั้งสามของคุณสืบทอด คุณสามารถแสดงนี้เป็นตารางที่เรียกว่ายกตัวอย่างเช่นplacesที่แต่ละแถวมีความสัมพันธ์แบบหนึ่งต่อหนึ่งกับแถวในregions, หรือcountries states(แอตทริบิวต์ที่ใช้ร่วมกันระหว่างภูมิภาคประเทศหรือรัฐหากมีสามารถผลักเข้าไปในตารางสถานที่นี้ได้) popular_place_idจากนั้นคุณจะเป็นรหัสอ้างอิงต่างประเทศไปยังแถวในตารางสถานที่ซึ่งจะนำคุณไปสู่ภูมิภาคประเทศ หรือรัฐ

โซลูชันที่คุณเสนอพร้อมคอลัมน์ที่สองเพื่ออธิบายประเภทของการเชื่อมโยงที่เกิดขึ้นเป็นวิธีที่ Rails จัดการกับการเชื่อมโยง polymorphic แต่ฉันไม่ใช่แฟนของเรื่องนั้น Bill อธิบายในรายละเอียดที่ดีว่าเหตุใดการเชื่อมโยง polymorphic จึงไม่ใช่เพื่อนของคุณ


1
อาคา "รูปแบบ supertype-subtype"
ErikE

นอกจากนี้บทความนี้แสดงให้เห็นถึงแนวคิดduhallowgreygeek.com/polymorphic-association-bad-sql-smell
Marco Staffoli

5

นี่คือการแก้ไขวิธีการ "supertable" ของ Bill Karwin โดยใช้คีย์ผสม( place_type, place_id )เพื่อแก้ไขการละเมิดรูปแบบการรับรู้ปกติ:

CREATE TABLE places (
  place_id INT NOT NULL UNIQUE,
  place_type VARCHAR(10) NOT NULL
     CHECK ( place_type = 'state', 'country' ),
  UNIQUE ( place_type, place_id )
);

CREATE TABLE states (
  place_id INT NOT NULL UNIQUE,
  place_type VARCHAR(10) DEFAULT 'state' NOT NULL
     CHECK ( place_type = 'state' ),
  FOREIGN KEY ( place_type, place_id ) 
     REFERENCES places ( place_type, place_id )
  -- attributes specific to states go here
);

CREATE TABLE countries (
  place_id INT NOT NULL UNIQUE,
  place_type VARCHAR(10) DEFAULT 'country' NOT NULL
     CHECK ( place_type = 'country' ),
  FOREIGN KEY ( place_type, place_id ) 
     REFERENCES places ( place_type, place_id )
  -- attributes specific to country go here
);

CREATE TABLE popular_areas (
  user_id INT NOT NULL,
  place_id INT NOT NULL,
  UNIQUE ( user_id, place_id ),
  FOREIGN KEY ( place_type, place_id ) 
     REFERENCES places ( place_type, place_id )
);

สิ่งที่การออกแบบนี้ไม่สามารถรับประกันได้ว่าสำหรับทุกแถวในplacesนั้นมีแถวในstatesหรือcountries(แต่ไม่ใช่ทั้งคู่) นี่เป็นข้อ จำกัด ของ foreign key ใน SQL ในมาตรฐานเต็มรูปแบบของ SQL-92 มาตรฐาน DBMS คุณสามารถกำหนดข้อ จำกัด ระหว่างตาราง deferrable ที่จะช่วยให้คุณสามารถบรรลุเหมือนกัน แต่มัน clunky เกี่ยวข้องกับการทำธุรกรรมและ DBMS ดังกล่าวยังไม่ได้ทำการตลาด


0

ฉันรู้ว่าหัวข้อนี้เก่า แต่ฉันเห็นสิ่งนี้และวิธีแก้ปัญหามาถึงใจและฉันคิดว่าฉันจะทิ้งมันไว้ที่นั่น

ภูมิภาคประเทศและรัฐเป็นที่ตั้งทางภูมิศาสตร์ที่อยู่ในลำดับชั้น

คุณสามารถหลีกเลี่ยงปัญหาของคุณได้ทั้งหมดด้วยการสร้างตารางโดเมนที่ชื่อว่า ge_location_type ซึ่งคุณจะเติมด้วยแถวสามแถว (ภูมิภาคประเทศรัฐ)

ถัดไปแทนตารางตำแหน่งสามตารางให้สร้างตาราง ge_location เดียวที่มี foreign key ของ ge_location_type_id (เพื่อให้คุณทราบว่าอินสแตนซ์นั้นเป็นภูมิภาคประเทศหรือรัฐ)

ทำโมเดลลำดับชั้นโดยการอ้างอิงตารางด้วยตนเองเพื่อให้อินสแตนซ์ของรัฐเก็บ fKey ให้กับอินสแตนซ์ของประเทศหลักซึ่งจะเก็บ fKey ให้กับอินสแตนซ์ของภูมิภาคหลัก อินสแตนซ์ของภูมิภาคจะถือ NULL ใน fKey นั้น สิ่งนี้ไม่แตกต่างจากสิ่งที่คุณทำกับสามตาราง (คุณจะมี 1 - ความสัมพันธ์จำนวนมากระหว่างภูมิภาคและประเทศและระหว่างประเทศและรัฐ) ยกเว้นตอนนี้มันอยู่ในตารางเดียว

ตาราง popular_user_location จะเป็นตารางการแก้ปัญหาขอบเขตระหว่างผู้ใช้และ georgraphical_location (ผู้ใช้จำนวนมากอาจต้องการสถานที่จำนวนมาก)

ซู ...

ป้อนคำอธิบายรูปภาพที่นี่

CREATE TABLE [geographical_location_type] (
    [geographical_location_type_id] INTEGER NOT NULL,
    [name] VARCHAR(25) NOT NULL,
    CONSTRAINT [PK_geographical_location_type] PRIMARY KEY ([geographical_location_type_id])
)

-- Add 'Region', 'Country' and 'State' instances to the above table


CREATE TABLE [geographical_location] (
   [geographical_location_id] BIGINT IDENTITY(0,1) NOT NULL,
    [name] VARCHAR(1024) NOT NULL,
    [geographical_location_type_id] INTEGER NOT NULL,
    [geographical_location_parent] BIGINT,  -- self referencing; can be null for top-level instances
    CONSTRAINT [PK_geographical_location] PRIMARY KEY ([geographical_location_id])
)

CREATE TABLE [user] (
    [user_id] BIGINT NOT NULL,
    [login_id] VARCHAR(30) NOT NULL,
    [password] VARCHAR(512) NOT NULL,
    CONSTRAINT [PK_user] PRIMARY KEY ([user_id])
)


CREATE TABLE [popular_user_location] (
    [popular_user_location_id] BIGINT NOT NULL,
    [user_id] BIGINT NOT NULL,
    [geographical_location_id] BIGINT NOT NULL,
    CONSTRAINT [PK_popular_user_location] PRIMARY KEY ([popular_user_location_id])
)

ALTER TABLE [geographical_location] ADD CONSTRAINT [geographical_location_type_geographical_location] 
    FOREIGN KEY ([geographical_location_type_id]) REFERENCES [geographical_location_type] ([geographical_location_type_id])



ALTER TABLE [geographical_location] ADD CONSTRAINT [geographical_location_geographical_location] 
    FOREIGN KEY ([geographical_location_parent]) REFERENCES [geographical_location] ([geographical_location_id])



ALTER TABLE [popular_user_location] ADD CONSTRAINT [user_popular_user_location] 
    FOREIGN KEY ([user_id]) REFERENCES [user] ([user_id])



ALTER TABLE [popular_user_location] ADD CONSTRAINT [geographical_location_popular_user_location] 
    FOREIGN KEY ([geographical_location_id]) REFERENCES [geographical_location] ([geographical_location_id])

ไม่แน่ใจว่า DB เป้าหมายคืออะไร ด้านบนคือ MS SQL Server


0

ฉันมีสองตาราง:

  1. เพลง

a) หมายเลขเพลง b) ชื่อเพลง ....

  1. รายการเพลง a) หมายเลขเพลย์ลิสต์ b) ชื่อเพลย์ลิสต์ ...

และฉันมีหนึ่งในสาม

  1. songs_to_playlist_relation

ปัญหาคือเพลย์ลิสต์บางประเภทมีลิงค์ไปยังเพลย์ลิสต์อื่น แต่ใน mysql เราไม่มี foreign key ที่เชื่อมโยงกับสองตาราง

ทางออกของฉัน: ฉันจะใส่คอลัมน์ที่สามใน songs_to_playlist_relation คอลัมน์นั้นจะเป็นบูลีน ถ้า 1 แล้วเพลงอื่นจะเชื่อมโยงไปยังตารางเพลย์ลิสต์

ดังนั้น:

  1. songs_to_playlist_relation

a) Playlist_number (int) b) เป็นเพลง (บูลีน) c) หมายเลขสัมพันธ์ (หมายเลขเพลงหรือหมายเลขเพลย์ลิสต์) (int) ( ไม่ใช่คีย์ต่างประเทศในตารางใด ๆ )

 # สร้างตาราง เพลงคำสั่ง
    ผนวก( "ตลาดหลักทรัพย์ sql_mode = NO_AUTO_VALUE_ON_ZERO;" ) คำสั่ง
    ผนวก( "สร้างตาราง( int (11) NOT NULL, int (11) NOT NULL, tinyint (1) NOT NFA DEFAULT '1', varchar (255) ชุดอักขระ CHARACTER utf8 COLLATE utf8_general_ci NOT NULL, varchar (1000) CHARACTER SET utf8 COLLATE utf8_general_ci ไม่ใช่ NULL, varchar (255) ชุดอักขระ UTF8 COLLATE utf8_general_ci ไม่เป็นค่าเริ่มต้นCHοςκαλλιτέχνης ', varchar (255) ชุดอักขระ UTF8_general_ci ไม่ใช่ NULL, varchar (255) ชุดอักขระ UTF8_general_ci ไม่ใช่ NULL เริ่มต้น 'Άγνωστοάλμπουμ'songsNUMBERSONG POSITIONPLAY SONGSONG TITLEDESCRIPTIONARTISTAUTHORCOMPOSER varchar (255) ชุดอักขระ UTF8_general_ci ไม่ใช่ NULL เริ่มต้น 'Άγνωστοςσυνθέτης'ALBUMYEAR int (11) ไม่เป็นค่าเริ่มต้น '33', RATINGint (11) ไม่เป็นค่าเริ่มต้น '5', IMAGEvarchar (600) ชุดอักขระ utf8 COLLATE utf8_general_ci NOT NULL, SONG PATHvarchar (500) ชุดอักขระ utf8 COLLATE utf8_general_ci ไม่ใช่ NULL, SONG REPEATint (11) ไม่เป็นค่าเริ่มต้น '0', VOLUMEลอยไม่ใช่ค่าเริ่มต้น '1', SPEEDเอ็นจิ้น ;" ) คำสั่ง
    ผนวก( "songsNUMBER) เพิ่มคีย์ที่ไม่ซ้ำกันPOSITION(SONG POSITION ), เพิ่ม UNIQUE KEY TITLE( SONG TITLE), เพิ่ม UNIQUE KEY PATH( SONG PATH);") 
    ข้อความค้นหา. ผนวก int (11) ไม่เป็นโมฆะ AUTO_INCREMENT;"( "แก้ไขตารางsongsแก้ไข)NUMBER

#create table playlists
queries.append("CREATE TABLE `playlists` (`NUMBER` int(11) NOT NULL,`PLAYLIST POSITION` int(11) NOT NULL,`PLAYLIST TITLE` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`PLAYLIST PATH` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
queries.append("ALTER TABLE `playlists` ADD PRIMARY KEY (`NUMBER`),ADD UNIQUE KEY `POSITION` (`PLAYLIST POSITION`),ADD UNIQUE KEY `TITLE` (`PLAYLIST TITLE`),ADD UNIQUE KEY `PATH` (`PLAYLIST PATH`);")
queries.append("ALTER TABLE `playlists` MODIFY `NUMBER` int(11) NOT NULL AUTO_INCREMENT;")

#create table for songs to playlist relation
queries.append("CREATE TABLE `songs of playlist` (`PLAYLIST NUMBER` int(11) NOT NULL,`SONG OR PLAYLIST` tinyint(1) NOT NULL DEFAULT '1',`RELATIVE NUMBER` int(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
queries.append("ALTER TABLE `songs of playlist` ADD KEY `PLAYLIST NUMBER` (`PLAYLIST NUMBER`) USING BTREE;")
queries.append("ALTER TABLE `songs of playlist` ADD CONSTRAINT `playlist of playlist_ibfk_1` FOREIGN KEY (`PLAYLIST NUMBER`) REFERENCES `playlists` (`NUMBER`) ON DELETE RESTRICT ON UPDATE RESTRICT")

นั่นคือทั้งหมด!

เพลย์ลิสต์query = "เลือก s1. *, s3. *, s4. * จากเพลงในฐานะ s1 INNER JOIN` เพลงของเพลย์ลิสต์ `เป็น s2 บน s1.NUMBER` = s2.` หมายเลขเข้าภายใน 'เพลย์ลิสต์' เป็น s3 ON s3 .`NUMBER` = s2.`PLAYLIST NUMBER` INNER JOIN `เพลย์ลิสต์ 'เป็น s4 บน s4.NUMBER` = s2.` หมายเลขการสั่งซื้อที่เกี่ยวข้อง' s1 '' เพลย์ลิสต์ตำแหน่ง ',' s1`''SONG POSITION`"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.