2010-09-11 30 views
5

Trong ứng dụng của chúng tôi người dùng có thể tạo danh sách khác nhau (như sharepoint), ví dụ người dùng có thể tạo danh sách xe ô tô (tên, mô hình, thương hiệu) và danh sách sinh viên (tên, dob, địa chỉ, quốc tịch), e.t.c.Cách ưu tiên để lưu danh sách động trong cơ sở dữ liệu là gì?

Ứng dụng của chúng tôi sẽ có thể truy vấn trên các cột khác nhau của danh sách để chúng tôi không thể tuần tự hóa từng hàng và lưu nó trong một hàng.

Tôi có nên tạo bảng mới trong thời gian chạy cho mỗi danh sách mới được tạo không? Nếu đây là giải pháp tốt nhất thì có lẽ Microsoft SharePoint cũng đã làm nó như tôi nghĩ?

Tôi có nên sử dụng sơ đồ sau

Lists (Id, Name) 
ListColumns (Id, ListId, Name) 
ListRows (Id, ListId) 
ListData(RowId, ColumnId, Value) 

Mặc dù một hàng duy nhất sẽ tạo bao nhiêu dòng trong bảng dữ liệu danh sách vì có các cột trong danh sách, điều này chỉ không cảm thấy đúng.

Bạn đã xử lý tình huống này chưa? Làm thế nào bạn xử lý nó trong cơ sở dữ liệu?

+1

Không tệ chút nào, nhưng thường quy ước là không sử dụng số nhiều. Đó là các tên bảng thường là List, ListColumn, ListRow, ListData. Các bảng có nhiều hơn một hàng, sử dụng số nhiều là thừa. – Hogan

Trả lời

1

Có lẽ một giải pháp tiềm năng sẽ là việc tạo danh sách có thể liên quan đến câu hỏi CREATE TABLE cho những thực thể/danh sách đó?

Có vẻ như cấu trúc db hoặc lược đồ có thể thay đổi khi chạy, hoặc tại lệnh của người dùng, vì vậy có lẽ điều gì đó như thế này có thể hữu ích?

  • Người dùng muốn tạo danh sách mới của một thực thể chưa từng thấy trước đây. Gọi nó là Máy tính.
  • tài khoản định nghĩa các thuộc tính (screensize, CpuSpeed, AmountRAM, NumberOfCores)
  • Hệ thống cho phép người dùng tạo ra trong hệ thống giao diện người dùng
  • thường cho phép họ tất cả có dây, trừ khi có thể nói khi tất cả các giá trị cung cấp có thực sự ngày hoặc số .
  • tạo tập lệnh CREATE, thực thi chúng với DB.
  • chèn dữ liệu mà người dùng đã xác định vào bảng mới đó.

Được mã hóa đúng cách, chúng tôi đang làm việc với các yêu cầu đã cho: cho phép người dùng tạo các đối tượng mới. Không có đề cập đến quy mô ở đây. Tất nhiên, điều này đòi hỏi tất cả đầu vào phải được khử trùng, các truy vấn được tham số hóa, các hành động được ghi lại, v.v.

Bình luận tiêu cực bên dưới không thực sự đưa ra lý do chính đáng, nhưng tạo ra một chút FUD. Tôi muốn được quan tâm đến việc giải quyết bất kỳ mối lo ngại nào với giải pháp tiềm năng này. Chúng tôi chưa từng nghe về quy mô, bảo mật, hiệu suất hoặc sử dụng (mạng LAN nội bộ so với Internet).

+6

Thật sao? Điều này nghe như một ý tưởng kinh khủng đối với tôi - theo nhiều cách. – Hogan

+5

Xin vui lòng, xin đừng làm điều này.Tôi chưa bao giờ thấy một trường hợp tốt cho việc tạo lập bảng, và điều này chắc chắn không bán cho tôi. Điều gì sẽ xảy ra nếu hai người dùng muốn tạo danh sách có cùng tên? Những gì bạn muốn là một bảng. Gọi nó là 'danh sách'. Tiến hành từ đó. – meagar

+0

@Hogan @meagar Giả sử mỗi người dùng đang làm việc với cơ sở dữ liệu cá nhân của riêng họ, điều này nghe có vẻ giống như giải pháp tốt nhất cho tôi - chắc chắn có một bảng 'danh sách' có thể * dường như * như một giải pháp" thuần khiết "tốt cho vấn đề nhưng bạn đã bao giờ đã thử viết một truy vấn để tham gia trên nhiều "bảng" khi tất cả dữ liệu thực sự nằm trong 1 bảng vật lý? Chưa kể rằng bạn có thể từ bỏ bất kỳ hy vọng bạn đã có trên nó thực sự thực hiện. – Justin

3

những gì bạn đã làm được gọi là EAV (Entity-Attribute-Value Model).

Đối với một danh sách với 3 cột và 1000 mục:

1 kỷ lục trong Lists 3 bản ghi trong ListColumns và 3000 Entries trong ListData

Điều này là tốt. Tôi không phải là một fan hâm mộ của việc tạo ra các bảng on-the-fly bởi vì nó có thể mess lên cơ sở dữ liệu của bạn và bạn sẽ phải "tạo" các truy vấn SQL của bạn động. Tôi sẽ có được một cảm giác lạ khi người dùng có thể TẠO/DROP/ALTER Bàn trong cơ sở dữ liệu của tôi!

Một tính năng thú vị khác của mô hình EAV là bạn có thể hợp nhất hai danh sách dễ dàng mà không cần thả và thay đổi bảng.

Edit:

Tôi nghĩ rằng bạn cần một bảng gọi là ListRows rằng sẽ cho bạn biết hồ sơ ListData thuộc về nhau trong một hàng!

+0

+1 cho câu trả lời này. Nó hoàn thành công việc và nó linh hoạt! Tôi sẽ theo dõi các vấn đề về sự hoàn hảo hoặc quy mô trong tương lai. –

+0

Bạn đang phải tôi bỏ lỡ các bảng hàng –

0

Có vẻ như bạn có thể có Sharepoint đã được triển khai trong môi trường của mình.

Cân nhắc tích hợp ứng dụng của bạn với Sharepoint và có đó là kho dữ liệu của bạn. Không cần phải tạo lại tất cả những thứ bạn thích về Sharepoint, khi bạn có thể tận dụng nó.

Nó sẽ mất một chút cấu hình, nhưng bạn có thể gọi dịch vụ web SP để CRUD dữ liệu danh sách của bạn cho bạn.

Sharepoint 2010 cũng có thể phơi bày danh sách qua OData, đó sẽ là đơn giản để tiêu thụ từ bất kỳ ứng dụng.

+0

Chúng tôi không thể có một nửa cơ sở dữ liệu trực tiếp trong máy chủ sql và phần còn lại trong SharePoint. –

1

Bạn hoàn toàn không nên tự động tạo bảng khi người dùng tạo danh sách. Đó không phải là cách cơ sở dữ liệu có nghĩa là để làm việc.

schema của bạn là chính xác, và pluralization là, theo ý kiến ​​của tôi, cũng đúng, mặc dù tôi sẽ loại bỏ các trường hợp lạc đà và gọi cho họ lists, list_columns, list_rowslist_data.

Tôi sẽ cải thiện thêm khi lược đồ của bạn bằng cách bỏ qua các bảng rowscolumns, chúng không phục vụ mục đích nào. Đơn giản chỉ cần có một hàng/cột số gắn liền với mỗi tế bào, và giữ cho mọi thứ thưa thớt: Đừng bận tâm giữ ô trống trong cơ sở dữ liệu. Bạn duy trì khả năng truy vấn/sắp xếp dựa trên hàng/cột, truy vấn của bạn sẽ có khả năng nhanh hơn vì số lượng list_cells sẽ bị giảm và bạn sẽ không phải tham gia bất kỳ hoạt động nào để liên kết dữ liệu của mình bảng của nó.

Dưới đây là sơ đồ hoàn chỉnh:

create table lists (
    id int primary key, 
    name varchar(25) not null 
); 

create table list_cells (
    id int primary key, 
    list_id int not null references lists(id) 
    on delete cascade on update cascade, 
    row int not null, 
    col int not null, 
    data varchar(25) not null 
); 
2

Vâng, tôi đã có kinh nghiệm một cái gì đó như thế này trước đây - Tôi không muốn chia sẻ schema bảng thực tế để cho phép thực hiện một số bài tập suy nghĩ sử dụng một số bảng gợi ý cấu trúc:

  • Cho phép có một bảng lists chứa một danh sách của tất cả các danh sách của tôi
  • cũng cho phép có một bảng columns chứa siêu dữ liệu (tên cột)
  • Bây giờ chúng ta cần một bảng values chứa các cột giá trị
  • Chúng ta cũng cần một bảng rows mà chứa một danh sách của tất cả các hàng, nếu không nó sẽ rất khó khăn để tìm ra bao nhiêu hàng có thực sự là

Để giữ cho mọi thứ đơn giản cho phép chỉ làm cho mọi thứ một chuỗi (VARCAHR) và có một đi vào đến với một số truy vấn:

Đếm tất cả các hàng trong một bảng

SELECT COUNT(*) FROM [rows] 
JOIN [lists] 
    ON [rows].list_id = [Lists].id 
WHERE [Lists].name = 'Cars' 

Hmm, không quá xấu, so với:

SELECT * FROM [Cars] 

Chèn một hàng vào một bảng

BEGIN TRANSACTION 

DECLARE @row_id INT 
DECLARE @list_id INT 

SELECT @list_id = id FROM [lists] WHERE name = 'Cars' 

INSERT INTO [rows] (list_id) VALUES (@list_id) 
SELECT @row_id = @@IDENTITY 

DECLARE @column_id INT 

-- === Need one of these for each column === 
SELECT @column_id = id FROM [columns] 
WHERE name = 'Make' 
AND list_id = @list_id 

INSERT INTO [values] (column_id, row_id, value) 
VALUES (@column_id, @row_id, 'Rover') 

-- === Need one of these for each column === 
SELECT @column_id = id FROM [columns] 
WHERE name = 'Model' 
AND list_id = @list_id 

INSERT INTO [values] (column_id, row_id, value) 
VALUES (@column_id, @row_id, 'Metro') 
COMMIT TRANSACTION 

Um, bắt đầu để có được một chút lông so với:

INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro') 

Đơn giản truy vấn

Tôi bây giờ chán xây dựng câu lệnh SQL tediously phức tạp như vậy có lẽ bạn có thể có một đi vào đến với truy vấn tương đương về những điều khoản followng:

SELECT [Model] FROM [Cars] WHRE [Make] = 'Rover' 

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars] 
JOIN [Owners] ON [Owners].id = [Cars].owner_id 
WHERE [Owners].Age > 50 

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars] 
JOIN [Owners] ON [Owners].id = [Cars].owner_id 
JOIN [Addresses] ON [Addresses].id = [Owners].address_id 
WHERE [Addresses].City = 'London' 

Tôi hy vọng bạn đang bắt đầu để có được ý tưởng ...

Tóm lại - Tôi đã trải qua điều này trước và tôi có thể đảm bảo với bạn rằng việc tạo cơ sở dữ liệu bên trong cơ sở dữ liệu theo cách này chắc chắn là một điều xấu.

Nếu bạn cần làm mọi thứ nhưng truy vấn cơ bản nhất trên các danh sách này (nghĩa đen là "Tôi có thể có tất cả các mục trong danh sách này không?"), Bạn nên thử thay thế.

Miễn là mỗi người dùng có khá nhiều cơ sở dữ liệu riêng, tôi chắc chắn sẽ giới thiệu phương pháp tiếp cận CREATE TABLE. Ngay cả khi họ không muốn tôi vẫn khuyên bạn nên ít nhất là xem xét nó.

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