Tại sao là Chọn Chọn * từ bảng.


96

Hôm qua tôi đã thảo luận với một lập trình viên "sở thích" (bản thân tôi là một lập trình viên chuyên nghiệp). Chúng tôi đã xem qua một số công việc của anh ấy và anh ấy nói anh ấy luôn truy vấn tất cả các cột trong cơ sở dữ liệu của mình (ngay cả trên / trong máy chủ / mã sản xuất).

Tôi đã cố gắng thuyết phục anh ta đừng làm như vậy, nhưng vẫn chưa thành công. Theo tôi, một lập trình viên chỉ nên truy vấn những gì thực sự cần thiết vì mục đích "hiệu quả", hiệu quả và lưu lượng truy cập. Tôi có nhầm với quan điểm của tôi không?


1
Tôi muốn nói rằng cos của nó nếu nội dung bảng thay đổi thì sao? thêm / xóa cột? bạn vẫn chọn * .. vì vậy bạn sẽ thiếu thứ hoặc lấy lại nhiều dữ liệu hơn mức bạn cần.
JF nó

2
@JFit Đó là một phần của nó, nhưng khác xa với toàn bộ câu chuyện.
jwenting

8
Những lý do chính đáng tại SO - stackoverflow.com/questions/3180375/select-vs-select-column
Bratch


@gnat một câu hỏi thực sự có thể được coi là một bản sao của một câu hỏi đóng? (tức là vì cái đóng không thực sự phù hợp ở nơi đầu tiên)
gbjbaanb

Câu trả lời:


67

Hãy suy nghĩ về những gì bạn sẽ nhận lại và cách bạn liên kết chúng với các biến trong mã của bạn.

Bây giờ hãy nghĩ điều gì xảy ra khi ai đó cập nhật lược đồ bảng để thêm (hoặc xóa) một cột, ngay cả một cột bạn không trực tiếp sử dụng.

Sử dụng select * khi bạn nhập truy vấn bằng tay là tốt, không phải khi bạn viết truy vấn cho mã.


8
Hiệu suất, tải mạng, v.v ... quan trọng hơn nhiều so với sự tiện lợi của việc lấy lại các cột theo thứ tự và với tên bạn muốn.
jwenting

21
@jwenting thật sao? hiệu suất quan trọng hơn sự đúng đắn? Dù sao, tôi không thấy rằng "select *" hoạt động tốt hơn là chỉ chọn các cột bạn muốn.
gbjbaanb

9
@Bratch, trong môi trường sản xuất thực tế, bạn có thể có hàng trăm ứng dụng sử dụng cùng một bảng và không có cách nào có thể duy trì đúng tất cả các ứng dụng đó. Bạn đúng trong tình cảm, nhưng thực tế, cuộc tranh cãi thất bại chỉ do thực tế làm việc trong copmiances. Thay đổi lược đồ cho các bảng hoạt động tất cả các thời gian.
dùng1068

18
Tôi không hiểu điểm trong câu trả lời này. Nếu bạn thêm một cột vào một bảng, cả CHỌN * và CHỌN [Cột] sẽ hoạt động, sự khác biệt duy nhất là nếu mã cần liên kết với cột mới, thì CHỌN [Cột] sẽ cần phải được sửa đổi trong khi CHỌN * sẽ không. Nếu một cột bị xóa khỏi một bảng, thì CHỌN * sẽ bị phá vỡ tại điểm liên kết, trong khi đó CHỌN [Cột] sẽ bị phá vỡ khi truy vấn được thực thi. Dường như với tôi rằng CHỌN * là tùy chọn linh hoạt hơn vì mọi thay đổi đối với bảng sẽ chỉ yêu cầu thay đổi đối với ràng buộc. Tui bỏ lỡ điều gì vậy?
TallGuy

11
@gbjbaanb sau đó truy cập các cột theo tên. Bất cứ điều gì khác rõ ràng sẽ là ngu ngốc trừ khi bạn chỉ định thứ tự cột trong truy vấn.
Immibis

179

Thay đổi lược đồ

  • Tìm nạp theo thứ tự --- Nếu mã đang tìm nạp cột # làm cách để lấy dữ liệu, một thay đổi trong lược đồ sẽ khiến các số cột điều chỉnh lại. Điều này sẽ làm rối ứng dụng và những điều xấu sẽ xảy ra.
  • Tìm nạp theo tên --- Nếu mã đang tìm nạp cột theo tên như foovà một bảng khác trong truy vấn sẽ thêm một cột foo, cách xử lý này có thể gây ra sự cố khi cố gắng lấy đúng foo cột.

Dù bằng cách nào, một sự thay đổi lược đồ có thể gây ra vấn đề với việc trích xuất dữ liệu.

Xem xét thêm nếu một cột đang được sử dụng được xóa khỏi bảng. Các select * from ...vẫn hoạt động nhưng lỗi ra khi cố gắng để kéo dữ liệu ra khỏi tập hợp kết quả. Nếu cột được chỉ định trong truy vấn, truy vấn sẽ báo lỗi thay vì đưa ra một dấu hiệu rõ ràng về vấn đề là gì và ở đâu.

Chi phí dữ liệu

Một số cột có thể có một lượng dữ liệu đáng kể liên quan đến chúng. Chọn trở lại *sẽ kéo tất cả dữ liệu. Đúng, đây là varchar(4096)trên 1000 hàng mà bạn đã chọn cung cấp cho bạn thêm 4 megabyte dữ liệu mà bạn không cần, nhưng được gửi qua đường dây.

Liên quan đến thay đổi lược đồ, varchar đó có thể không tồn tại ở đó khi bạn lần đầu tiên tạo bảng, nhưng bây giờ nó ở đó.

Không truyền đạt ý định

Khi bạn chọn trở lại *và nhận 20 cột nhưng chỉ cần 2 cột, bạn không truyền đạt được ý định của mã. Khi nhìn vào truy vấn mà select *người ta không biết phần quan trọng của nó là gì. Tôi có thể thay đổi truy vấn để sử dụng gói khác thay thế để làm cho nó nhanh hơn bằng cách không bao gồm các cột này không? Tôi không biết vì mục đích của những gì truy vấn trả về không rõ ràng.


Hãy xem xét một số câu đố SQL khám phá các lược đồ đó thay đổi nhiều hơn một chút.

Đầu tiên, cơ sở dữ liệu ban đầu: http://sqlfiddle.com/#!2/a67dd/1

DDL:

create table one (oneid int, data int, twoid int);
create table two (twoid int, other int);

insert into one values (1, 42, 2);
insert into two values (2, 43);

SQL:

select * from one join two on (one.twoid = two.twoid);

Và các cột mà bạn nhận lại được oneid=1, data=42, twoid=2, và other=43.

Bây giờ, điều gì xảy ra nếu tôi thêm một cột vào bảng một? http://sqlfiddle.com/#!2/cd0b0/1

alter table one add column other text;

update one set other = 'foo';

Và kết quả của tôi từ cùng một truy vấn như trước đây là oneid=1, data=42, twoid=2, và other=foo.

Một thay đổi trong một trong các bảng sẽ phá vỡ các giá trị của a select *và đột nhiên ràng buộc 'khác' của bạn với một int sẽ gây ra lỗi và bạn không biết tại sao.

Nếu thay vào đó, câu lệnh SQL của bạn là

select 
    one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);

Việc thay đổi bảng một sẽ không làm gián đoạn dữ liệu của bạn. Truy vấn đó chạy giống nhau trước khi thay đổi và sau khi thay đổi.


Lập chỉ mục

Khi bạn làm một, select * frombạn đang kéo tất cả các hàng tạo thành tất cả các bảng phù hợp với các điều kiện. Ngay cả các bảng bạn thực sự không quan tâm. Trong khi điều này có nghĩa là nhiều dữ liệu được chuyển đi, có một vấn đề hiệu suất khác ẩn sâu hơn trong ngăn xếp.

Chỉ số. (liên quan đến SO: Làm thế nào để sử dụng chỉ mục trong câu lệnh select? )

Nếu bạn đang lấy lại nhiều cột, trình tối ưu hóa kế hoạch cơ sở dữ liệu có thể bỏ qua việc sử dụng một chỉ mục bởi vì bạn vẫn sẽ cần tìm nạp tất cả các cột đó và sẽ mất nhiều thời gian hơn để sử dụng chỉ mục và sau đó tìm nạp tất cả các cột trong truy vấn hơn là chỉ cần thực hiện quét bảng hoàn chỉnh.

Nếu bạn chỉ chọn, giả sử họ của người dùng (bạn làm rất nhiều và có chỉ mục trên đó), cơ sở dữ liệu có thể thực hiện quét chỉ mục ( chỉ mục wiki chỉ quét , quét toàn bộ bảng mys mys so với toàn bộ quét chỉ mục , Quét chỉ mục : Tránh truy cập bảng ).

Có khá nhiều tối ưu hóa về việc chỉ đọc từ các chỉ mục nếu có thể. Thông tin có thể được kéo nhanh hơn trên mỗi trang chỉ mục vì bạn cũng lấy ít thông tin hơn - bạn không kéo theo tất cả các cột khác cho select *. Có thể một chỉ mục chỉ quét để trả về kết quả theo thứ tự nhanh hơn 100 lần (nguồn: Chọn * là xấu ).

Điều này không nói rằng quét chỉ mục đầy đủ là tuyệt vời, nó vẫn là quét toàn bộ - nhưng tốt hơn quét toàn bộ bảng. Một khi bạn bắt đầu theo đuổi tất cả những cách select *gây tổn hại đến hiệu suất, bạn tiếp tục tìm ra những cách mới.

Đọc liên quan


2
@Tonny Tôi đồng ý - nhưng khi tôi trả lời (lần đầu tiên) tôi chưa bao giờ nghĩ câu hỏi này sẽ tạo ra quá nhiều thảo luận và bình luận! Rõ ràng chỉ truy vấn các cột được đặt tên, phải không?!
gbjbaanb

3
Phá vỡ mọi thứ bằng cách thêm một cột cũng là một lý do chính đáng tại sao mã phải luôn truy cập các cột trong bộ dữ liệu theo tên chứ không phải theo thứ tự mã hóa cứng ...
Julia Hayward

1
@gbjbaanb Đó là với tôi. Nhưng rất nhiều người đến để viết các truy vấn SQL mà không có một nền tảng / đào tạo chính thức. Đối với họ có thể không rõ ràng.
Tonny

1
@Aaronaught Tôi đã cập nhật nó với bit bổ sung về các vấn đề lập chỉ mục. Có bất kỳ điểm nào khác mà tôi nên đưa ra cho sự sai trái của select *?

3
Wow, câu trả lời được chấp nhận rất kém khi thực sự giải thích bất cứ điều gì mà tôi đã bỏ phiếu. Kinh ngạc vì đây không phải là câu trả lời được chấp nhận. +1.
Ben Lee

38

Một mối quan tâm khác: nếu đó là một JOINtruy vấn và bạn đang truy xuất các kết quả truy vấn vào một mảng kết hợp (như trường hợp trong PHP), thì đó là lỗi dễ xảy ra.

Điều này là

  1. nếu bảng foocó cột idname
  2. nếu bảng barcó cột idaddress,
  3. và trong mã của bạn, bạn đang sử dụng SELECT * FROM foo JOIN bar ON foo.id = bar.id

đoán xem điều gì sẽ xảy ra khi ai đó thêm một cột namevào barbảng.

Mã sẽ đột nhiên ngừng hoạt động đúng cách, vì bây giờ namecột xuất hiện trong kết quả hai lần và nếu bạn lưu trữ kết quả vào một mảng, dữ liệu từ giây name( bar.name) sẽ ghi đè lên đầu tiên name( foo.name)!

Đó là một lỗi khá khó chịu vì nó rất không rõ ràng. Có thể mất một lúc để tìm ra, và không có cách nào người thêm một cột khác vào bảng có thể lường trước được tác dụng phụ không mong muốn như vậy.

(Câu chuyện có thật).

Vì vậy, không sử dụng *, hãy kiểm soát những cột bạn đang truy xuất và sử dụng bí danh khi thích hợp.


không sao trong trường hợp này (mà tôi coi là loại hiếm) nó có thể là một vấn đề lớn. Nhưng bạn vẫn có thể tránh (và hầu hết mọi người có thể sẽ) bằng cách truy vấn bằng ký tự đại diện và chỉ cần thêm bí danh cho các tên cột giống hệt nhau.
quá trình phân vùng

4
Về lý thuyết, nhưng nếu bạn sử dụng ký tự đại diện để thuận tiện, bạn dựa vào nó để tự động cung cấp cho bạn tất cả các cột tồn tại và không bao giờ bận tâm cập nhật truy vấn khi các bảng phát triển. Nếu bạn chỉ định từng cột, bạn buộc phải truy vấn để thêm một cột khác vào SELECTmệnh đề của bạn và đây là khi bạn hy vọng phát hiện ra tên không phải là duy nhất. BTW Tôi không nghĩ nó quá hiếm trong các hệ thống có cơ sở dữ liệu lớn. Như tôi đã nói, tôi đã từng dành vài giờ để săn lùng lỗi này trong một trận bóng bùn lớn của mã PHP. Và tôi đã tìm thấy một trường hợp khác ngay bây giờ: stackoverflow.com/q/17715049/168719
Konrad Morawski

3
Tôi dành một giờ tuần trước để cố gắng có được điều này thông qua người đứng đầu tư vấn. Anh ta được cho là một chuyên gia SQL ... Thở dài ...
Tonny

22

Truy vấn mọi cột có thể là hoàn toàn hợp pháp, trong nhiều trường hợp.

Luôn luôn truy vấn mọi cột không.

Nó hoạt động nhiều hơn cho công cụ cơ sở dữ liệu của bạn, nó phải tắt và lục lọi xung quanh siêu dữ liệu nội bộ của nó để tìm ra cột nào cần xử lý trước khi có thể bắt tay vào công việc thực sự là lấy dữ liệu và gửi lại cho bạn. OK, nó không phải là chi phí lớn nhất trên thế giới, nhưng danh mục hệ thống có thể là một nút cổ chai đáng kể.

Đó là công việc nhiều hơn cho mạng của bạn, bởi vì bạn đang rút lại bất kỳ số lượng trường nào khi bạn có thể chỉ muốn một hoặc hai trong số chúng. Nếu ai đó [khác] đi và thêm một vài chục trường bổ sung, tất cả đều chứa các đoạn văn bản lớn, thông lượng của bạn đột nhiên đi qua sàn - không có lý do rõ ràng. Điều này trở nên tồi tệ hơn nếu mệnh đề "ở đâu" của bạn không đặc biệt tốt và bạn cũng đang rút lại rất nhiều hàng - điều đó có khả năng rất nhiều dữ liệu đang truyền qua mạng cho bạn (tức là nó sẽ bị chậm).

Ứng dụng của bạn hoạt động nhiều hơn, phải rút lại và lưu trữ tất cả dữ liệu bổ sung này mà có lẽ nó không quan tâm lắm.

Bạn có nguy cơ cột thay đổi thứ tự của họ. OK, bạn không cần phải lo lắng về điều này (và bạn sẽ không nếu bạn chỉ chọn các cột bạn cần), nhưng, nếu bạn đi lấy tất cả chúng cùng một lúc và ai đó [người khác] quyết định sắp xếp lại thứ tự cột trong bảng , được xuất một cách cẩn thận, xuất CSV mà bạn cung cấp cho các tài khoản xuống hội trường đột nhiên chuyển sang nồi - một lần nữa, không có lý do rõ ràng.

BTW, tôi đã nói "ai đó [khác]" một vài lần, ở trên. Hãy nhớ rằng cơ sở dữ liệu vốn đã đa người dùng; bạn có thể không kiểm soát chúng mà bạn nghĩ bạn làm.


3
Tôi nghĩ rằng việc luôn truy vấn mọi cột có thể là hợp pháp đối với những thứ như các phương tiện xem bảng không xác định lược đồ. Không phải là một tình huống phổ biến khủng khiếp, nhưng trong bối cảnh các công cụ chỉ sử dụng nội bộ, những thứ như vậy có thể có ích.
supercat

1
@supercat Đó chỉ là về trường hợp sử dụng hợp lệ DUY NHẤT cho "CHỌN *" mà tôi có thể nghĩ ra. Và thậm chí sau đó tôi muốn giới hạn truy vấn là "CHỌN TOP 10 *" (trong MS SQL) hoặc thêm "LIMIT 10" (myQuery) hoặc thêm "WHERE ROWNUM <= 10" (Oracle). Thông thường trong trường hợp đó, nó nói nhiều hơn về "cột nào ở đó và một số dữ liệu mẫu" hơn là nội dung hoàn chỉnh.
Tonny

@Tonny: SQL Server đã thay đổi các tập lệnh mặc định của họ để thêm TOPgiới hạn; Tôi không chắc điều đó quan trọng đến mức nào nếu mã đọc nhiều như nó quan tâm để hiển thị và sau đó loại bỏ truy vấn. Tôi nghĩ rằng các câu trả lời truy vấn được xử lý hơi lười biếng, mặc dù tôi không biết chi tiết. Trong mọi trường hợp, tôi nghĩ rằng thay vì nói rằng nó "không phải là hợp pháp", nó sẽ là tốt hơn để nói "... là hợp pháp ở xa ít"; về cơ bản, tôi tóm tắt các trường hợp hợp pháp là những trường hợp người dùng sẽ có ý tưởng tốt hơn về ý nghĩa của lập trình viên.
supercat

@supercat Tôi có thể đồng ý với điều đó. Và tôi thực sự thích cách bạn đặt nó trong câu cuối cùng của bạn. Tôi phải nhớ cái đó
Tonny

11

Câu trả lời ngắn gọn là: nó phụ thuộc vào cơ sở dữ liệu họ sử dụng. Cơ sở dữ liệu quan hệ được tối ưu hóa để trích xuất dữ liệu bạn cần một cách nhanh chóng, đáng tin cậy và nguyên tử . Trên các bộ dữ liệu lớn và các truy vấn phức tạp, nó nhanh hơn và an toàn hơn nhiều so với CHỌN * và thực hiện tương đương với các phép nối ở phía 'mã'. Các cửa hàng giá trị khóa có thể không được triển khai các chức năng như vậy hoặc có thể không đủ chín chắn để sử dụng trong sản xuất.

Điều đó nói rằng, bạn vẫn có thể điền vào bất kỳ cấu trúc dữ liệu nào bạn đang sử dụng với SELECT * và tìm ra phần còn lại trong mã nhưng bạn sẽ thấy các tắc nghẽn về hiệu suất nếu bạn muốn chia tỷ lệ.

So sánh gần nhất là sắp xếp dữ liệu: bạn có thể sử dụng quicksort hoặc bubbleort và kết quả sẽ chính xác. Nhưng sẽ không được tối ưu hóa và chắc chắn sẽ có vấn đề khi bạn giới thiệu đồng thời và cần sắp xếp nguyên tử.

Tất nhiên, việc thêm RAM và CPU rẻ hơn so với đầu tư vào một lập trình viên có thể thực hiện các truy vấn SQL và thậm chí có một sự hiểu biết mơ hồ về THAM GIA là gì.


Học SQL! Nó không khó lắm đâu. Đây là ngôn ngữ "bản địa" của cơ sở dữ liệu xa và rộng. Nó mạnh mẽ. Thật thanh lịch. Nó đã đứng trước thử thách của thời gian. Và không có cách nào bạn sẽ viết một phép nối ở phía "mã" hiệu quả hơn việc tham gia vào cơ sở dữ liệu, trừ khi bạn thực sự không có khả năng thực hiện các phép nối SQL. Hãy xem xét rằng để thực hiện "nối mã", bạn phải lấy tất cả dữ liệu từ cả hai bảng trong một phép nối 2 bảng đơn giản. Hoặc bạn đang kéo các số liệu thống kê chỉ mục và sử dụng chúng để quyết định dữ liệu bảng nào sẽ được kéo trước khi bạn tham gia? Đừng nghĩ vậy ... Học cách sử dụng cơ sở dữ liệu một cách chính xác, mọi người.
Craig

@Craig: SQL là phổ biến trong các cơ sở dữ liệu quan hệ xa và rộng. Tuy nhiên, đó là loại DB duy nhất, mặc dù ... và có một lý do các cách tiếp cận cơ sở dữ liệu hiện đại hơn thường được gọi là NoQuery. : P Không ai tôi biết sẽ gọi SQL là "tao nhã" mà không có sự mỉa mai nặng nề. Nó chỉ hút ít hơn nhiều lựa chọn thay thế, khi có liên quan đến cơ sở dữ liệu quan hệ.
cHao

@cHao Tôi đã nhận thức được rất nhiều loại cơ sở dữ liệu khác nhau trong nhiều thập kỷ . Cơ sở dữ liệu Pick "nosql" đã tồn tại mãi mãi. "NoQuery" thậm chí không phải là một khái niệm mới. ORM cũng đã tồn tại mãi mãi và chúng luôn chậm. Chậm! = Tốt. Đối với sự thanh lịch (LINQ?), Bạn không thể thuyết phục tôi điều này là hợp lý hay thanh lịch cho một điều khoản ở đâu: Customer customer = this._db.Customers.Where( “it.ID = @ID”, new ObjectParameter( “ID”, id ) ).First();Xem Thời gian để thực hiện hành vi phạm tội trên trang 2.
Craig

@Craig: Đừng để tôi bắt đầu với ORM. Gần như mọi hệ thống ngoài kia làm điều đó một cách khủng khiếp, và sự trừu tượng bị rò rỉ khắp nơi. Đó là bởi vì các bản ghi DB quan hệ không phải là các đối tượng - tốt nhất, chúng là các phần tử tuần tự hóa của một phần của một đối tượng. Nhưng đối với LINQ, bạn thực sự muốn đến đó? Tương đương SQLish giống như var cmd = db.CreateCommand(); cmd.CommandText = "SELECT TOP 1 * FROM Customers WHERE ID = @ID"; cmd.Parameters.AddWithValue("@ID", id); var result = cmd.ExecuteReader();.... và sau đó tiến hành tạo Khách hàng từ mỗi hàng. LINQ đánh bại cái quần đó.
cHao

@Craig: Cấp, nó không thanh lịch như nó có thể. Nhưng nó sẽ không bao giờ thanh lịch như tôi muốn cho đến khi nó có thể chuyển đổi mã .net thành SQL. :) Tại điểm mà bạn có thể nói var customer = _db.Customers.Where(it => it.id == id).First();.
cHao

8

IMO, về việc rõ ràng so với ngầm. Khi tôi viết mã, tôi muốn nó hoạt động vì tôi đã làm cho nó hoạt động, không chỉ vì tất cả các phần chỉ xảy ra ở đó. Nếu bạn truy vấn tất cả các bản ghi và mã của bạn hoạt động, thì bạn sẽ có xu hướng tiếp tục. Sau này nếu có gì đó thay đổi và bây giờ mã của bạn không hoạt động, việc gỡ lỗi rất nhiều truy vấn và hàm tìm kiếm một giá trị nên có và tham chiếu giá trị duy nhất là *.

Cũng theo cách tiếp cận tầng N, cách tốt nhất là cách ly sự gián đoạn lược đồ cơ sở dữ liệu với tầng dữ liệu. Nếu tầng dữ liệu của bạn chuyển * sang logic nghiệp vụ và rất có thể trên tầng trình bày, bạn đang mở rộng phạm vi gỡ lỗi của mình theo cấp số nhân.


3
Đây có lẽ là một trong những lý do quan trọng nhất ở đây và nó chỉ nhận được một phần rất nhỏ trong số phiếu bầu. Khả năng duy trì của một codebase rải rác select *là tồi tệ hơn nhiều!
Eamon Nerbonne

6

bởi vì nếu bảng có các cột mới thì bạn sẽ có được tất cả những cột đó ngay cả khi bạn không cần chúng. với varcharsđiều này có thể trở thành rất nhiều dữ liệu bổ sung cần phải đi từ DB

một số tối ưu hóa DB cũng có thể trích xuất các bản ghi độ dài không cố định thành một tệp riêng để tăng tốc truy cập vào các phần có độ dài cố định, sử dụng select * đánh bại mục đích của điều đó


1

Ngoài chi phí, bạn muốn tránh điều gì đó ngay từ đầu, tôi sẽ nói rằng với tư cách là một lập trình viên, bạn không phụ thuộc vào thứ tự cột được xác định bởi quản trị viên cơ sở dữ liệu. Bạn chọn từng cột ngay cả khi bạn cần tất cả.


3
Đồng ý, mặc dù tôi cũng khuyên bạn nên rút các giá trị từ kết quả được đặt theo tên cột trong mọi trường hợp.
Rory Hunter

Biệt phái, thực hiện. Sử dụng tên cột, không phụ thuộc vào thứ tự cột. Thứ tự cột là một phụ thuộc giòn. Các tên nên có (bạn hy vọng) được lấy từ một số nỗ lực thiết kế thực tế hoặc bạn rõ ràng bí danh các cột tổng hợp hoặc tính toán hoặc tên cột xung đột trong truy vấn của bạn và tham chiếu bí danh rõ ràng mà bạn đã chỉ định. Nhưng dựa vào trật tự là khá nhiều chỉ là băng keo và lời cầu nguyện ...
Craig

1

Tôi không thấy bất kỳ lý do nào khiến bạn không nên sử dụng cho mục đích xây dựng - lấy tất cả các cột từ cơ sở dữ liệu. Tôi thấy ba trường hợp:

  1. Một cột được thêm vào cơ sở dữ liệu và bạn cũng muốn nó trong mã. a) Với * sẽ thất bại với một thông điệp thích hợp. b) Không có * sẽ hoạt động, nhưng sẽ không làm những gì bạn mong đợi, điều này khá tệ.

  2. Một cột được thêm vào cơ sở dữ liệu và bạn không muốn nó trong mã. a) Với * sẽ thất bại; điều này có nghĩa là * không còn áp dụng vì ngữ nghĩa của nó có nghĩa là "lấy tất cả". b) Không có * sẽ hoạt động.

  3. Một cột bị xóa Mã sẽ không thành công.

Bây giờ trường hợp phổ biến nhất là trường hợp 1 (vì bạn đã sử dụng * có nghĩa là tất cả những gì bạn có thể muốn nhất); không có * bạn có thể có mã hoạt động tốt nhưng không thực hiện được những gì được mong đợi, điều tồi tệ nhất là mã bị lỗi với thông báo lỗi thích hợp .

Tôi không xem xét mã lấy dữ liệu cột dựa trên chỉ mục cột dễ bị lỗi theo quan điểm của tôi. Nó hợp lý hơn nhiều để lấy nó dựa trên tên cột.


Tiền đề của bạn là không chính xác. Select *được dự định nhiều hơn để thuận tiện cho truy vấn đặc biệt, không nhằm mục đích phát triển ứng dụng. Hoặc để sử dụng trong các cấu trúc thống kê như select count(*)cho phép công cụ truy vấn quyết định có nên sử dụng chỉ mục, chỉ mục nào sẽ sử dụng hay không và bạn không trả về bất kỳ dữ liệu cột thực tế nào. Hoặc để sử dụng trong các mệnh đề như where exists( select * from other_table where ... ), một lần nữa là một lời mời đến công cụ truy vấn để tự mình chọn đường dẫn hiệu quả nhất và truy vấn con chỉ được sử dụng để hạn chế kết quả từ truy vấn chính. V.v.
Craig

@Craig Tôi tin rằng mọi cuốn sách / hướng dẫn về SQL đều nói rằng select *có ngữ nghĩa của việc truy xuất tất cả các cột; nếu ứng dụng của bạn thực sự cần điều này, tôi không thấy bất kỳ lý do nào tại sao không sử dụng nó. Bạn có thể chỉ ra một số tài liệu tham khảo (Oracle, IBM, Microsoft, v.v.) đề cập đến mục đích select *xây dựng không phải là để lấy tất cả các cột không?
m3th0dman

Tất nhiên, select *tồn tại để lấy tất cả các cột ... như một tính năng tiện lợi, cho truy vấn đặc biệt, không phải vì đó là một ý tưởng tuyệt vời trong phần mềm sản xuất. Các lý do đã được trình bày khá rõ trong các câu trả lời trên trang này, đó là lý do tại sao tôi không tạo ra câu trả lời chi tiết của riêng mình: •) Các vấn đề về hiệu suất, liên tục xử lý dữ liệu qua mạng mà bạn không bao giờ sử dụng, •) các vấn đề với răng cưa cột, •) thất bại kế hoạch truy vấn tối ưu hóa (thất bại trong việc sử dụng các chỉ số trong một số trường hợp), •) không hiệu quả server I / O trong trường hợp giới hạn chọn có thể chỉ sử dụng chỉ số vv
Craig

Có thể có một trường hợp cạnh ở đây hoặc ở đó biện minh cho việc sử dụng select *trong một ứng dụng sản xuất thực tế, nhưng bản chất của trường hợp cạnh là nó không phải là trường hợp phổ biến . :-)
Craig

@Craig Lý do là không truy xuất tất cả các cột từ cơ sở dữ liệu không chống lại việc sử dụng select *; những gì tôi đã nói nếu bạn thực sự cần tất cả các cột, tôi thấy không có lý do tại sao bạn không nên sử dụng select *; mặc dù ít phải có kịch bản trong đó tất cả các cột là cần thiết.
m3th0dman

1

Hãy nghĩ về nó theo cách này ... nếu bạn truy vấn tất cả các cột từ một bảng chỉ có một vài chuỗi nhỏ hoặc trường số, tổng số 100k dữ liệu. Thực hành xấu, nhưng nó sẽ thực hiện. Bây giờ thêm một trường duy nhất chứa, giả sử, hình ảnh hoặc tài liệu từ 10mb. bây giờ truy vấn hiệu suất nhanh của bạn ngay lập tức và bắt đầu hoạt động kém một cách bí ẩn, chỉ vì một trường được thêm vào bảng ... bạn có thể không cần yếu tố dữ liệu khổng lồ đó, nhưng vì bạn đã hoàn thành Select * from Tablenên bạn vẫn nhận được nó.


6
điều này dường như chỉ lặp lại điểm đã được thực hiện vài giờ trước trong câu trả lời đầu tiên và trong một vài câu trả lời khác
gnat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.