SELECT *
to select all columns of a particular table. Typing
SELECT * FROM ...
is much simpler and less work than typing say
SELECT order_id, order_date FROM ...
.SELECT *
in production code.
SELECT *
are:
-- DROP VIEW dbo.complete_orders -- DROP TABLE dbo.orderlines -- DROP TABLE dbo.orders CREATE TABLE dbo.orders (order_id int NOT NULL CONSTRAINT PK_orders PRIMARY KEY NONCLUSTERED ,order_date datetime NOT NULL ,description char(300) NULL ,shipped_date datetime NULL ,amount_paid decimal(15,2) NULL ,full_info varchar(max) NULL ,cs XML column_set FOR ALL_SPARSE_COLUMNS ) CREATE INDEX IX_orders_orderdate ON dbo.orders(order_date) INCLUDE (order_id) CREATE TABLE dbo.orderlines (orderlines_order_id int NOT NULL CONSTRAINT FK_orderlines_orders REFERENCES dbo.orders ,line_number tinyint NOT NULL ,article_number int NULL ,amount tinyint NULL ,price decimal(15,2) NULL ,last_change_date datetime NULL ,CONSTRAINT PK_orderlines PRIMARY KEY CLUSTERED (orderlines_order_id,line_number) ) INSERT INTO dbo.orders(order_id,order_date,amount_paid,full_info) VALUES (1,'20100801',14,REPLICATE('a',100000)) INSERT INTO dbo.orders(order_id,order_date,amount_paid,full_info) VALUES (2,'20100802',14,REPLICATE('b',200000)) INSERT INTO dbo.orders(order_id,order_date,amount_paid,full_info) VALUES (3,'20100803',14,REPLICATE('c',300000)) INSERT INTO dbo.orders(order_id,order_date,amount_paid,full_info) VALUES (4,'20100804',14,REPLICATE('d',400000)) INSERT INTO dbo.orders(order_id,order_date,amount_paid) VALUES (5,'20100805',15) INSERT INTO dbo.orders(order_id,order_date,amount_paid) VALUES (6,'20100806',9.95) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (1,1) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (1,2) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (2,1) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (3,1) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (3,2) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (3,3) INSERT INTO dbo.orderlines(orderlines_order_id,line_number) VALUES (4,1) INSERT INTO dbo.orderlines(orderlines_order_id,line_number,amount,price) VALUES (5,1,4,2.50) INSERT INTO dbo.orderlines(orderlines_order_id,line_number,amount,price) VALUES (5,2,1,5) INSERT INTO dbo.orderlines(orderlines_order_id,line_number,last_change_date) VALUES (6,1,'20100806') INSERT INTO dbo.orderlines(orderlines_order_id,line_number,last_change_date) VALUES (6,2,'20100807')
SELECT *
you ask for all columns.
-- Select orders in date range -- include I/O statistics SET STATISTICS IO ON GO SELECT * FROM orders WHERE order_date BETWEEN '20100802' AND '20100805' GO SET STATISTICS IO OFF
varchar(max)
column in it. This data is (normally) not stored
on the same disk page that holds the rest of the column data, but it is stored in lob (Large Object) pages.varchar(max)
, nvarchar(max)
,
varbinary(max)
,
text
, ntext
and image
. The only exception is when the actual data
in the column is so small that it would fit on the same page as the rest of the columns, and the table
configuration allows inline storage of lob columns.Table 'orders'. Scan count 1, logical reads 1, physical reads 1, read-ahead reads 0, lob logical reads 7, lob physical reads 3, lob read-ahead reads 0.
-- Select orders in date range; relevant columns only -- include I/O statistics SET STATISTICS IO ON GO SELECT order_id, order_date, amount_paid FROM orders WHERE order_date BETWEEN '20100802' AND '20100805' GO SET STATISTICS IO OFF
Table 'orders'. Scan count 1, logical reads 1, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SELECT *
you ask for all columns.
-- Select orders in date range SELECT * FROM orders WHERE order_date BETWEEN '20100802' AND '20100805'
-- Select orders in date range; relevant columns only SELECT order_id, order_date FROM orders WHERE order_date BETWEEN '20100802' AND '20100805'
SELECT *
. The application that uses these queries,
are they actively using this column, the one that needs to be dropped? You don't know! At least
not until you've investigated these applications as well.CREATE VIEW dbo.complete_orders AS SELECT * FROM orders JOIN orderlines ON orderlines_order_id = order_id
-- select complete orders of August 5th SELECT * FROM complete_orders WHERE order_date = '20100805'
ALTER TABLE dbo.orders ADD return_date datetime NULL -- select complete orders of August 5th SELECT * FROM dbo.complete_orders WHERE order_date = '20100805'
orderlines_order_id
. All other column's values have been moved one column to the right. The column
last_change_date
now lists money amounts. Can you see the problems this will cause for the application(s)
that use the view?sp_refreshview "dbo.complete_orders"
SELECT *
to select from multiple tables. Like this:
-- select everything of August 6th SELECT * FROM orders, orderlines WHERE orderlines_order_id = order_id AND order_date = '20100806'
last_change_date
.
With the current query, it would get 2010-08-06
and 2010-08-07
.last_change_date
column to the orders table as well.
ALTER TABLE orders ADD last_change_date datetime NULL
SELECT *
query.-- select everything of August 6th SELECT * FROM orders, orderlines WHERE orderlines_order_id = order_id AND order_date = '20100806'
last_date_change
.
The orderlines last_date_change
column is no longer available, except when using the column's
index number (which would have caused problems in this example as well)!-- refreshing the view after a table modification sp_refreshview "dbo.complete_orders"
Server: Msg 4506, Level 16, State 1, Procedure sp_refreshsqlmodule_internal, Line 75 Column names in each view or function must be unique. Column name 'last_change_date' in view or function 'complete_orders' is specified more than once.
SPARSE
.-- select everything of August 6th SELECT * FROM orders, orderlines WHERE orderlines_order_id = order_id AND order_date = '20100806'
amount_paid
a sparse column.ALTER TABLE orders ALTER COLUMN amount_paid decimal(15,2) SPARSE NULL
SELECT *
query.-- select everything of August 6th SELECT * FROM orders, orderlines WHERE orderlines_order_id = order_id AND order_date = '20100806'
amount_paid
column, because
SELECT *
will not select it. Instead, the column cs
will contain its value
in XML format.SELECT *
in an EXISTS
clause. Like this:-- SELECT * in EXISTS() is just fine! SELECT order_id, order_date, amount_paid FROM orders WHERE EXISTS ( SELECT * FROM orderlines WHERE orderlines_order_id = order_id AND amount IS NOT NULL AND price IS NOT NULL )
SELECT *
in this EXISTS
clause
does not actually select any columns. It indicates that the columns don't matter.
Back to SQL Server main menu. Mail your comments to gertjans@xs4all.nl.