อะไรคือเหตุผลที่จะไม่ใช้ select *


136

ฉันเคยเห็นผู้คนจำนวนมากอ้างว่าคุณควรตั้งชื่อแต่ละคอลัมน์ที่คุณต้องการในข้อความค้นหาที่เลือก

สมมติว่าฉันจะใช้คอลัมน์ทั้งหมดทำไมฉันจะไม่ใช้SELECT *?

แม้จะพิจารณาคำถาม * แบบสอบถาม SQL - เลือก * จากมุมมองหรือเลือก col1, col2, … colN จากมุมมอง * ฉันไม่คิดว่านี่เป็นคำซ้ำซ้อนเนื่องจากฉันกำลังเข้าใกล้ปัญหาจากมุมมองที่แตกต่างกันเล็กน้อย

หนึ่งในหลักการของเราคือการไม่ปรับให้เหมาะสมก่อนถึงเวลา โดยที่ในใจดูเหมือนว่าการใช้SELECT *ควรเป็นวิธีการที่ต้องการจนกว่าจะได้รับการพิสูจน์แล้วว่าเป็นปัญหาทรัพยากรหรือสคีมาที่ตั้งอยู่ในหินสวยมาก ซึ่งอย่างที่เรารู้จะไม่เกิดขึ้นจนกว่าการพัฒนาจะเสร็จสมบูรณ์

ที่กล่าวว่ามีปัญหาสำคัญที่จะไม่ใช้SELECT *หรือไม่

คำตอบ:


168

สาระสำคัญของการอ้างถึงการเพิ่มประสิทธิภาพที่ไม่ได้กำหนดไว้ล่วงหน้าคือการใช้รหัสที่ง่ายและตรงไปตรงมาจากนั้นใช้ profiler เพื่อระบุฮอตสปอตซึ่งคุณสามารถเพิ่มประสิทธิภาพให้มีประสิทธิภาพได้

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


ดังนั้นการเลือกคอลัมน์ไม่ใช่การเพิ่มประสิทธิภาพก่อนวัยอันควร มีบางสิ่งที่อยู่ด้านบนหัวของฉัน ....

  1. หากคุณระบุคอลัมน์ในคำสั่ง SQL เอ็นจินการเรียกใช้งาน SQL จะเกิดข้อผิดพลาดหากคอลัมน์นั้นถูกลบออกจากตารางและเรียกใช้คิวรี
  2. คุณสามารถสแกนรหัสที่ใช้คอลัมน์นั้นได้ง่ายขึ้น
  3. คุณควรเขียนแบบสอบถามเพื่อนำข้อมูลจำนวนน้อยที่สุดกลับมา
  4. ตามที่คนอื่นพูดถึงถ้าคุณใช้การเข้าถึงคอลัมน์ลำดับคุณไม่ควรใช้ select *
  5. หากคำสั่ง SQL ของคุณรวมตารางให้เลือก * ให้คอลัมน์ทั้งหมดจากตารางทั้งหมดในการเข้าร่วม

ข้อพิสูจน์คือการใช้select *...

  1. คอลัมน์ที่ใช้โดยแอปพลิเคชันนั้นทึบแสง
  2. DBA และโปรไฟล์ตัวสอบถามของพวกเขาไม่สามารถช่วยให้แอปพลิเคชันของคุณมีประสิทธิภาพต่ำ
  3. รหัสมีความเปราะเมื่อการเปลี่ยนแปลงเกิดขึ้น
  4. ฐานข้อมูลและเครือข่ายของคุณกำลังทุกข์ทรมานเพราะพวกเขานำข้อมูลกลับมามากเกินไป (I / O)
  5. การปรับแต่งเอนจินฐานข้อมูลให้น้อยที่สุดเมื่อคุณนำข้อมูลทั้งหมดกลับมาโดยไม่คำนึงถึง

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


2
ในส่วนแรกของคุณจุด # 5 ควรอ่าน "select * ให้คอลัมน์ทั้งหมดจากตารางทั้งหมดในการเข้าร่วม" ในส่วนที่สองของคุณคะแนน # 2 และ # 5 ไม่จำเป็นต้องเป็นจริงและไม่ควรแสดงเป็นเหตุผลที่ไม่ใช้ "select *"
jimmyorr

1
@uglysmurf - ขอบคุณสำหรับการแก้ไข แต่เกี่ยวกับ 2 & 5 - ในขณะที่พวกเขาอาจไม่เป็นจริงสำหรับฐานข้อมูล / dba ทั้งหมดในทุกกรณีฉันรู้สึกว่าพวกเขามีความสำคัญและถูกต้องสำหรับกรณีส่วนใหญ่และจะปล่อยพวกเขามา การใช้ 'select *' ไม่ทำให้งานของ dba ง่ายขึ้น
Robert Paulson

11
ฉันขอยืนยันว่า # 3 (รหัสเปราะ) ไม่เป็นความจริง Select * อาจทำให้เปราะน้อย แต่ขึ้นอยู่กับการใช้งาน แต่ฉันไม่เห็นว่ามันจะมีมากขึ้นได้อย่างไร
JohnFx

2
@ JohnFx ฉันเดาว่าคุณนิยามเปราะแตกต่างกัน เปราะมักถูกกำหนดให้เป็น 'ตัวแบ่งได้ง่าย' การมีการพึ่งพาที่ไม่รู้จักหรือยากต่อการค้นหาเพราะโค้ดแต่ละชิ้นจะใช้คอลัมน์ที่แตกต่างกันซึ่งหมายความว่าฉันไม่สามารถเปลี่ยนแปลงอะไรในระดับข้อมูลได้อย่างง่ายดายหากไม่มีการถดถอยแบบเต็ม .. ซึ่งดูเหมือนจะเปราะบาง
Robert Paulson

9
@mavnn, wrt brittleness, ฉันกลัวว่านี่จะกลายเป็นประเด็นความหมายในการเลือกคำว่าเปราะ คำพูดสุดท้ายของฉันคือการพูดว่ามันสร้างความแตกต่างเล็กน้อยอย่างไรก็ตาม สถานการณ์เดียวเท่านั้นที่ถูกเปลี่ยนชื่อ / ลบคอลัมน์ คุณเพียงแค่ย้ายตัวแบ่งจากเมื่อ sql ถูกดำเนินการ (ชัดเจน) กับตัวแบ่งเมื่อผลลัพธ์ถูกใช้ วิธีที่ผลลัพธ์ของการสืบค้นนั้นแตกต่างกันไปและรหัสอาจหรือไม่อาจล้มเหลวอย่างเงียบ ๆ แต่เอ็นจินการเรียกใช้งาน sql จะล้มเหลวอย่างแน่นอนด้วย sql ที่ไม่ถูกต้อง ดังนั้น * เลือกช่วยคุณได้หรือไม่ IMO ล้มเหลวอย่างชัดเจนใกล้กับฐานข้อมูลสำหรับปัญหา DB จะดีกว่า ขอบคุณ
Robert Paulson

42

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

เพียงเพราะคุณกำลังใช้คอลัมน์ทั้งหมดตอนนี้ไม่ได้หมายความว่าคนอื่นจะไม่เพิ่มคอลัมน์พิเศษลงในตาราง

นอกจากนี้ยังเพิ่มค่าใช้จ่ายในการแคชการดำเนินการตามแผนเนื่องจากต้องดึงข้อมูลเมตาเกี่ยวกับตารางเพื่อให้ทราบว่าคอลัมน์ใดอยู่ใน *


4
คำตอบที่ดี แต่ฉันจะเปลี่ยน "รหัสจะแตก" เป็น "รหัสอาจหยุดพัก" นั่นเป็นปัญหาจริงที่นี่การใช้ "select *" ไม่ได้ทำให้เกิดการเปลี่ยนแปลง และเมื่อการแตกเกิดขึ้นมักจะถูกแยกออกอย่างมากจากการใช้ที่สิ้นสุดลง
BQ

4
หากมีใครบางคนกำลังอ้างอิงคอลัมน์ตามปกติในรหัสของพวกเขาพวกเขากำลังมีปัญหาโดยไม่คำนึงว่าพวกเขาใช้ SELECT * หรือไม่ ค่าใช้จ่ายในการดำเนินการตามแผนนั้นไม่สำคัญและจะไม่สำคัญเมื่อแผนถูกแคช
MusiGenesis

1
จากนั้นโปรแกรมเมอร์ผิดพลาดอยู่ในการเขียนรหัสที่ขึ้นอยู่กับลำดับของคอลัมน์ คุณไม่จำเป็นต้องทำเช่นนั้น
dkretz

1
@doofledorfer - ไม่เคยพูดไม่เคย มันเร็วกว่าในการเข้าถึงคอลัมน์ลำดับและมันเป็นประโยชน์ในบางครั้ง เป็นข้อผิดพลาดที่ใหญ่กว่าในการใช้ select * มากกว่าที่จะใช้การเข้าถึงตามลำดับ
Robert Paulson

23

หนึ่งในเหตุผลสำคัญคือถ้าคุณเคยเพิ่ม / ลบคอลัมน์ออกจากตารางของคุณแบบสอบถาม / ขั้นตอนใด ๆ ที่ทำให้การเรียกใช้ SELECT * จะได้รับคอลัมน์ของข้อมูลมากกว่าหรือน้อยกว่าที่คาดไว้


3
คุณไม่ควรเขียนโค้ดที่ขึ้นอยู่กับจำนวนคอลัมน์ที่ส่งคืน
dkretz

4
แต่ทุกคนกำลังเขียนโค้ดที่ต้องการให้โปรแกรมเมอร์รู้ว่าข้อมูลใดกำลังจะกลับมา คุณไม่สามารถ Ctrl + F ชื่อคอลัมน์ของคุณหากมันซ่อนอยู่ใน SELECT *
Lotus Notes

17
  1. ในทางอ้อมคุณกำลังฝ่าฝืนกฎแบบแยกส่วนเกี่ยวกับการใช้การพิมพ์แบบเข้มงวดทุกที่ที่ทำได้ อย่างชัดเจนเกือบดีขึ้นในระดับสากล

  2. แม้ว่าตอนนี้คุณต้องการทุกคอลัมน์ในตารางก็สามารถเพิ่มได้อีกในภายหลังซึ่งจะถูกดึงลงมาทุกครั้งที่คุณเรียกใช้แบบสอบถามและอาจทำให้ประสิทธิภาพลดลง มันเจ็บประสิทธิภาพเพราะ

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

ควรใช้เมื่อใดให้เลือก *

เมื่อคุณต้องการทุกคอลัมน์ในตารางอย่างชัดเจนแทนที่จะต้องการทุกคอลัมน์ในตารางที่มีอยู่ในเวลาที่คุณเสียคำ ตัวอย่างเช่นหากกำลังเขียนแอปการจัดการฐานข้อมูลที่จำเป็นต้องแสดงเนื้อหาทั้งหมดของตาราง (ไม่ว่าจะเกิดอะไรขึ้น) คุณอาจใช้วิธีการนั้น


1
อีกครั้งที่จะใช้SELECT *ก็คือเมื่อคุณทำแบบสอบถามทดสอบโดยใช้ไคลเอนต์ db
cdmckay

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

และเลือก * จาก (เลือก a, b, c จากตาราง) ด้วย
kmkaplan

12

มีสาเหตุบางประการ:

  1. หากจำนวนคอลัมน์ในฐานข้อมูลเปลี่ยนแปลงและแอปพลิเคชันของคุณคาดว่าจะมีจำนวนที่แน่นอน ...
  2. หากลำดับของคอลัมน์ในฐานข้อมูลเปลี่ยนแปลงและแอปพลิเคชันของคุณคาดว่าจะอยู่ในลำดับที่แน่นอน ...
  3. หน่วยความจำเหนือศีรษะ 8 คอลัมน์ INTEGER ที่ไม่จำเป็นจะเพิ่มหน่วยความจำที่สูญเสียไป 32 ไบต์ ไม่ได้เสียงมากนัก แต่สำหรับแต่ละแบบสอบถามและ INTEGER เป็นหนึ่งในประเภทคอลัมน์ขนาดเล็ก ... คอลัมน์พิเศษมีแนวโน้มที่จะเป็นคอลัมน์ VARCHAR หรือ TEXT ซึ่งจะเพิ่มขึ้นอย่างรวดเร็ว
  4. ค่าใช้จ่ายเครือข่าย เกี่ยวข้องกับค่าใช้จ่ายในหน่วยความจำ: ถ้าฉันออกแบบสอบถาม 30,000 รายการและมีคอลัมน์ INTEGER 8 รายการที่ไม่จำเป็นฉันเสียแบนด์วิดท์ 960kB ไปแล้ว คอลัมน์ VARCHAR และ TEXT น่าจะมีขนาดใหญ่กว่ามาก

หมายเหตุ: ฉันเลือก INTEGER ในตัวอย่างด้านบนเนื่องจากมีขนาดคงที่ 4 ไบต์


1 และ 2 จะเป็นรหัสกลิ่นและเสียง 3 และ 4 เช่นการปรับให้เหมาะสมก่อนวัย
NikkyD

7

หากแอปพลิเคชันของคุณได้รับข้อมูลด้วย SELECT * และโครงสร้างตารางในฐานข้อมูลมีการเปลี่ยนแปลง (พูดว่าลบคอลัมน์) แอปพลิเคชันของคุณจะล้มเหลวในทุกที่ที่คุณอ้างอิงถึงฟิลด์ที่ขาดหายไป หากคุณรวมคอลัมน์ทั้งหมดในแบบสอบถามของคุณแทนแอปพลิเคชันของคุณจะแตกใน (หวังว่า) ที่เดียวที่คุณเริ่มรับข้อมูลในตอนแรกทำให้การแก้ไขง่ายขึ้น

ดังที่กล่าวไว้มีหลายสถานการณ์ที่ต้องการ SELECT * หนึ่งคือสถานการณ์ที่ฉันพบตลอดเวลาที่ฉันต้องทำซ้ำทั้งตารางลงในฐานข้อมูลอื่น (เช่น SQL Server กับ DB2 เป็นต้น) อีกอย่างคือแอปพลิเคชันที่เขียนขึ้นเพื่อแสดงตารางทั่วไป (เช่นไม่มีความรู้เกี่ยวกับตารางใด ๆ โดยเฉพาะ)


คำถามไม่ใช่ 'เลือก * เคยเป็นที่ต้องการ' ดังนั้นส่วนที่ 2 ของคำตอบของคุณจึงไม่เกี่ยวข้อง คำถามระบุว่าการใช้ 'select *' ควรจะดีกว่าซึ่งแน่นอนว่าเป็น bollock ที่สมบูรณ์
Robert Paulson

ใช่ส่วนที่ 2 ของฉันไม่เกี่ยวข้อง OQ เปลี่ยนคำถามเป็นสถานะ SELECT * ดีกว่าและใช่แล้วนั่นเป็นสิ่งที่มีประโยชน์มาก
MusiGenesis

อ่าใช่แล้ว - คำถามเปลี่ยนไปแล้วหลังจากคำตอบของคุณ
Robert Paulson

ไม่เป็นไร. แม้แต่ Mozart ก็เป็นบรรณาธิการ ( stackoverflow.com/questions/292682/… ) โพสต์ต้นฉบับของฉันแนะนำว่าการใช้ SELECT * นำไปสู่การกินเนื้อคน :)
MusiGenesis

3

ฉันสังเกตเห็นพฤติกรรมแปลก ๆ เมื่อฉันใช้select *ในมุมมองใน SQL Server 2005

เรียกใช้แบบสอบถามต่อไปนี้แล้วคุณจะเห็นว่าฉันหมายถึงอะไร

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','c1'
union all select 'a2','b2','c2'
union all select 'a3','b3','c3'

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vStartest]'))
DROP VIEW [dbo].[vStartest]
go
create view dbo.vStartest as
select * from dbo.starTest
go

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vExplicittest]'))
DROP VIEW [dbo].[vExplicittest]
go
create view dbo.[vExplicittest] as
select a,b,c from dbo.starTest
go


select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicitTest

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [D] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','d1','c1'
union all select 'a2','b2','d2','c2'
union all select 'a3','b3','d3','c3'

select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicittest

เปรียบเทียบผลลัพธ์ของข้อความสั่งการเลือก 2 รายการล่าสุด ฉันเชื่อว่าสิ่งที่คุณจะเห็นเป็นผลมาจากการเลือก *การอ้างอิงคอลัมน์ตามดัชนีแทนที่จะเป็นชื่อ

หากคุณสร้างมุมมองใหม่มันจะทำงานได้ดีอีกครั้ง

แก้ไข

ฉันได้เพิ่มคำถามที่แยกต่างหาก * “ เลือก * จากตาราง” และ“ เลือก colA, colB และอื่น ๆ จากตาราง” พฤติกรรมที่น่าสนใจใน SQL Server 2005 * เพื่อดูพฤติกรรมที่มีรายละเอียดเพิ่มเติม


2

คุณอาจเข้าร่วมสองตารางและใช้คอลัมน์ A จากตารางที่สอง หากภายหลังคุณเพิ่มคอลัมน์ A ลงในตารางแรก (ด้วยชื่อเดียวกัน แต่อาจมีความหมายที่แตกต่างกัน) คุณจะได้รับค่าจากตารางแรกและไม่ใช่คอลัมน์ที่สองเหมือนก่อนหน้า สิ่งนี้จะไม่เกิดขึ้นหากคุณระบุคอลัมน์ที่คุณต้องการเลือกอย่างชัดเจน

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


2

ฉันเข้าใจว่าคุณกำลังจะไปถึงการเพิ่มประสิทธิภาพก่อนวัยอันควร แต่นั่นไปถึงจุด ๆ เท่านั้น จุดประสงค์คือเพื่อหลีกเลี่ยงการเพิ่มประสิทธิภาพที่ไม่จำเป็นในการเริ่มต้น ตารางของคุณไม่มีการทำดัชนีหรือไม่? คุณจะใช้ nvarchar (4000) เพื่อจัดเก็บรหัสไปรษณีย์หรือไม่?

ตามที่คนอื่น ๆ ระบุไว้มีข้อดีอื่น ๆ ที่จะระบุแต่ละคอลัมน์ที่คุณต้องการใช้ในแบบสอบถาม (เช่นการบำรุงรักษา)


2

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


1
ฉันไม่รู้ว่าใครเป็น Feuerstein พยายาม googling และพบนักจิตวิทยาตัวละครโทรทัศน์และบล็อกเกอร์ดังนั้นสิ่งที่ดีที่สุดที่ฉันจะได้รับคือเรื่องตลก
NotMe

ผู้แต่งหนังสือ O'Reilly บน PL / SQL ลองใช้ "feuerstein sql" ของ Google แทน "feuerstein" เพียงอย่างเดียว
orbfish

2

SELECT *ไม่ใช่ความชั่วเสมอไป ในความคิดของฉันอย่างน้อย ฉันใช้บ่อยครั้งสำหรับคิวรีแบบไดนามิกที่ส่งคืนทั้งตารางรวมทั้งฟิลด์ที่คำนวณได้

ตัวอย่างเช่นฉันต้องการคำนวณรูปทรงทางภูมิศาสตร์จากตาราง "ปกติ" นั่นคือตารางที่ไม่มีเขตข้อมูลรูปทรงเรขาคณิต แต่มีเขตข้อมูลที่มีพิกัด ฉันใช้ postgresql และ postgis ส่วนขยายเชิงพื้นที่ แต่หลักการใช้สำหรับกรณีอื่น ๆ อีกมากมาย

ตัวอย่าง:

  • ตารางของสถานที่ที่มีพิกัดที่เก็บไว้ในฟิลด์ที่มีข้อความ x, y, z:

    สร้างสถานที่ตาราง (จำนวนเต็ม place_id, x ตัวเลข (10, 3), y ตัวเลข (10, 3), ตัวเลข z (10, 3), คำอธิบาย varchar);

  • มาป้อนค่าตัวอย่างดังนี้

    INSERT INTO places (place_id, x, y, z, description) ค่า
    (1, 2.295, 48.863, 64, 'Paris, Place de l \' Étoile '),
    (2, 2.945, 48.858, 40,' Paris, Tour Eiffel '),
    (3, 0.373, 43.958, 90,' Condom, Cathédrale St-Pierre ');

  • ฉันต้องการแมปเนื้อหาของตารางนี้โดยใช้ไคลเอ็นต์ GIS บางตัว วิธีปกติคือการเพิ่มเขตข้อมูลเรขาคณิตลงในตารางและสร้างรูปทรงเรขาคณิตขึ้นอยู่กับพิกัด แต่ฉันต้องการที่จะได้รับแบบสอบถามแบบไดนามิก: ด้วยวิธีนี้เมื่อฉันเปลี่ยนพิกัด (การแก้ไขความแม่นยำมากขึ้น ฯลฯ ) วัตถุที่แมปจะย้ายจริงแบบไดนามิก ดังนั้นนี่คือแบบสอบถามด้วยSELECT * :

    สร้างหรือแทนที่ดู places_points ตามที่
    เลือก *,
    GeomFromewkt ('SRID = 4326; POINT (' || x || '' || y || '| | z ||') ')
    จากสถานที่;

    อ้างถึง postgis สำหรับการใช้ฟังก์ชัน GeomFromewkt ()

  • นี่คือผลลัพธ์:

    SELECT * จาก places_points;

place_id | x | y | z | คำอธิบาย | geomfromewkt                            
---------- + ------- + -------- + -------- + ------------- ----------------- + -------------------------------- ------------------------------------  
        1 | 2.295 | 48.863 | 64.000 | ปารีส, Place de l'Étoile | 01010000A0E61000005C8FC2F5285C02405839B4C8766E48400000000000005040  
        2 | 2.945 | 48.858 | 40.000 | Paris, Tour Eiffel | 01010000A0E61000008FC2F5285C8F0740E7FBA9F1D26D48400000000000004440
        3 | 0.373 | 43.958 | 90.000 ถุงยางอนามัย, Cathédrale St-Pierre | 01010000A0E6100000AC1C5A643BDFD73FB4C876BE9FFA45400000000000805640
(3 lignes)

ขณะนี้โปรแกรม GIS ใด ๆ สามารถใช้คอลัมน์ขวาสุดเพื่อจับคู่คะแนนได้อย่างถูกต้อง

  • หากในอนาคตมีการเพิ่มบางฟิลด์ลงในตาราง: ไม่ต้องกังวลฉันต้องเรียกใช้นิยาม VIEW เดียวกันอีกครั้ง

ฉันต้องการคำจำกัดความของมุมมองที่สามารถเก็บรักษาไว้ "ตามที่เป็นอยู่" โดยใช้ * แต่hélasไม่ใช่กรณีนี้: นี่เป็นวิธีการจัดเก็บภายในโดย postgresql:

SELECT places.place_id, places.x, places.y, places.z, places.description, geomfromewkt ((((((('SRID = 4326; POINT (' :: text || places.x)) || '': : text) || places.y) || '' :: text) || places.z) || ')' :: text) ตามตำแหน่ง geomfromewkt จากตำแหน่ง;


1

แม้ว่าคุณจะใช้ทุกคอลัมน์ แต่จะจัดการกับแถวของแถวด้วยดัชนีตัวเลขคุณจะพบปัญหาหากคุณเพิ่มแถวอื่นในภายหลัง

ดังนั้นโดยทั่วไปมันเป็นคำถามของการบำรุงรักษา! หากคุณไม่ได้ใช้ตัวเลือก * คุณจะไม่ต้องกังวลกับข้อความค้นหาของคุณ


1

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

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


1

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


1

เพื่อตอบคำถามของคุณโดยตรง: อย่าใช้ "SELECT *" เมื่อมันทำให้โค้ดของคุณมีความเปราะบางต่อการเปลี่ยนแปลงในตารางพื้นฐาน รหัสของคุณควรแตกเมื่อมีการเปลี่ยนแปลงในตารางที่มีผลโดยตรงกับข้อกำหนดของโปรแกรมของคุณ

แอปพลิเคชันของคุณควรใช้ประโยชน์จากเลเยอร์นามธรรมที่การเข้าถึงเชิงสัมพันธ์มีให้


1

ฉันไม่ได้ใช้ SELECT * เพียงเพราะมันเป็นเรื่องดีที่ได้เห็นและรู้ว่าฉันกำลังดึงข้อมูลในสาขาใด


1

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


1

ไม่เป็นไรเมื่อคุณทำexists(select * ...)เพราะไม่เคยมีการขยาย มิฉะนั้นจะมีประโยชน์จริง ๆ เท่านั้นเมื่อสำรวจตารางด้วย statments เลือกชั่วคราวหรือถ้าคุณมี CTE ที่กำหนดไว้ด้านบนและคุณต้องการให้ทุกคอลัมน์โดยไม่ต้องพิมพ์พวกเขาทั้งหมดอีกครั้ง


1

เพียงเพิ่มสิ่งหนึ่งที่ไม่มีใครพูดถึง Select *ส่งคืนคอลัมน์ทั้งหมดบางคนอาจเพิ่มคอลัมน์ในภายหลังซึ่งคุณไม่ต้องการให้ผู้ใช้สามารถเห็นได้เช่นผู้ที่อัปเดตข้อมูลล่าสุดหรือบันทึกเวลาหรือบันทึกย่อที่ผู้จัดการเท่านั้นที่ควรเห็นผู้ใช้ไม่ทั้งหมดเป็นต้น

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


0

เพราะ "select *" จะทำให้เสียหน่วยความจำเมื่อคุณไม่ต้องการทุกฟิลด์ แต่สำหรับเซิร์ฟเวอร์ sql การแสดงของพวกเขาจะเหมือนกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.