Showing posts with label field. Show all posts
Showing posts with label field. Show all posts

Tuesday, March 27, 2012

Collation problem

Hi all.
I have a problem with collation in SQLServer database. My table contains few
rows in field of type char(20),
field and server Collation is set to Croatian_CI_AS (Windows collation).
When I execute query SELECT field FROM table ORDER BY field, return set is
ordered as follows
---
field
---
+
-
7
7-
7+
7+1
71
7-1
72
Why does value 7-1 is placed between values 71 and 72 and not after 7+1.
Is there any way to tell SQLServer to set order of returned resultset in the
same way that windows
would set order of files in explorer. Collation Croatian_CI_AS is important
for me because of
correct order of special Croatian characters.

TomislavTomislav Stilinovi (Tomislav.Stilinovic@.zg.htnet.hr) writes:
> I have a problem with collation in SQLServer database. My table contains
> few rows in field of type char(20), field and server Collation is set to
> Croatian_CI_AS (Windows collation). When I execute query SELECT field
> FROM table ORDER BY field, return set is ordered as follows
> ---
> field
> ---
> +
> -
> 7
> 7-
> 7+
> 7+1
> 71
> 7-1
> 72
> Why does value 7-1 is placed between values 71 and 72 and not after 7+1.

I think most Unicode sorting algorithms with some level of sophistication
considers hyphen to be an ignorable character, at least on primary level.
This is also how you sort in a dictionary.

> Is there any way to tell SQLServer to set order of returned resultset in
> the same way that windows would set order of files in explorer.

No. And it appears that the one that is really the odd one out is
Explorer. I entered your data in Word, and asked it to sort, and I
got the same result as in SQL Server.

I ran my tests with Finnish_Swedish collations, and regional settings
set to Swedish, but I don't think this makes a difference in this case.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp

Sunday, March 25, 2012

Collation issue

Dear fellows,
Sometimes when I obtain a script for tables and then I copy them to another
Sql Server, collation at field level is lost. Why?
Thank you very much,If no specifiy coallation is named on the column, it wont be scripted.
HTH, Jens Suessmeyer.
http://www.sqlserver2005.de
"Enric" <Enric@.discussions.microsoft.com> schrieb im Newsbeitrag
news:6322A9EB-4603-43C6-BC2C-09DBB81F45D3@.microsoft.com...
> Dear fellows,
> Sometimes when I obtain a script for tables and then I copy them to
> another
> Sql Server, collation at field level is lost. Why?
> Thank you very much,

collation issue

Hi,
I am trying to change the collation of a database
from TblA of ServerA , i look at the field's collation which says "database
default" and i looked into it which says "SQL Collation"
SQL_Latin1_General_CP1_CI_AS
so i issued this statement
ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
collation ?
after that statment , shldn't it be changed to Windows Collation -->
LATIN_General_BIN ?
kindly advise
tks & rdgs
after i have issued the statement i looked in TblA but the collation is now
also "SQL_Latin1_General_CP1_CI_AS"No. That changes the database collation and any new objects (provided you
don't explicitely declare a different collation when you create them) will
have that default. You have to issue ALTER statements for every character
column though and change each of them. Don't forget about the indexes, whic
h
you also have to change.
--
MeanOldDBA
derrickleggett@.hotmail.com
http://weblogs.sqlteam.com/derrickl
When life gives you a lemon, fire the DBA.
"maxzsim" wrote:

> Hi,
> I am trying to change the collation of a database
> from TblA of ServerA , i look at the field's collation which says "databas
e
> default" and i looked into it which says "SQL Collation"
> SQL_Latin1_General_CP1_CI_AS
> so i issued this statement
> ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
> collation ?
> after that statment , shldn't it be changed to Windows Collation -->
> LATIN_General_BIN ?
> kindly advise
> tks & rdgs
> after i have issued the statement i looked in TblA but the collation is no
w
> also "SQL_Latin1_General_CP1_CI_AS"|||Hi ,
i c but how do i actually change the collation for the indexes now ?
apprecite ur advice
tks & rdgs
"MeanOldDBA" wrote:
[vbcol=seagreen]
> No. That changes the database collation and any new objects (provided you
> don't explicitely declare a different collation when you create them) will
> have that default. You have to issue ALTER statements for every character
> column though and change each of them. Don't forget about the indexes, wh
ich
> you also have to change.
> --
> MeanOldDBA
> derrickleggett@.hotmail.com
> http://weblogs.sqlteam.com/derrickl
> When life gives you a lemon, fire the DBA.
>
> "maxzsim" wrote:
>|||> i c but how do i actually change the collation for the indexes now ?
You don't. Drop the index. Change collation for the columns. Create the inde
x.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"maxzsim" <maxzsim@.discussions.microsoft.com> wrote in message
news:BA2027F4-F137-4014-918F-E9045C55B63F@.microsoft.com...[vbcol=seagreen]
> Hi ,
> i c but how do i actually change the collation for the indexes now ?
> apprecite ur advice
> tks & rdgs
> "MeanOldDBA" wrote:
>|||Hi,
tks for ur reply
rdgs,
"Tibor Karaszi" wrote:

> You don't. Drop the index. Change collation for the columns. Create the in
dex.
> --
> Tibor Karaszi, SQL Server MVP
> http://www.karaszi.com/sqlserver/default.asp
> http://www.solidqualitylearning.com/
> Blog: http://solidqualitylearning.com/blogs/tibor/
>
> "maxzsim" <maxzsim@.discussions.microsoft.com> wrote in message
> news:BA2027F4-F137-4014-918F-E9045C55B63F@.microsoft.com...
>

collation issue

Hi,
I am trying to change the collation of a database
from TblA of ServerA , i look at the field's collation which says "database
default" and i looked into it which says "SQL Collation"
SQL_Latin1_General_CP1_CI_AS
so i issued this statement
ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
collation ?
after that statment , shldn't it be changed to Windows Collation -->
LATIN_General_BIN ?
kindly advise
tks & rdgs
after i have issued the statement i looked in TblA but the collation is now
also "SQL_Latin1_General_CP1_CI_AS"No. That changes the database collation and any new objects (provided you
don't explicitely declare a different collation when you create them) will
have that default. You have to issue ALTER statements for every character
column though and change each of them. Don't forget about the indexes, which
you also have to change.
--
MeanOldDBA
derrickleggett@.hotmail.com
http://weblogs.sqlteam.com/derrickl
When life gives you a lemon, fire the DBA.
"maxzsim" wrote:
> Hi,
> I am trying to change the collation of a database
> from TblA of ServerA , i look at the field's collation which says "database
> default" and i looked into it which says "SQL Collation"
> SQL_Latin1_General_CP1_CI_AS
> so i issued this statement
> ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
> collation ?
> after that statment , shldn't it be changed to Windows Collation -->
> LATIN_General_BIN ?
> kindly advise
> tks & rdgs
> after i have issued the statement i looked in TblA but the collation is now
> also "SQL_Latin1_General_CP1_CI_AS"|||Hi ,
i c but how do i actually change the collation for the indexes now ?
apprecite ur advice
tks & rdgs
"MeanOldDBA" wrote:
> No. That changes the database collation and any new objects (provided you
> don't explicitely declare a different collation when you create them) will
> have that default. You have to issue ALTER statements for every character
> column though and change each of them. Don't forget about the indexes, which
> you also have to change.
> --
> MeanOldDBA
> derrickleggett@.hotmail.com
> http://weblogs.sqlteam.com/derrickl
> When life gives you a lemon, fire the DBA.
>
> "maxzsim" wrote:
> > Hi,
> >
> > I am trying to change the collation of a database
> >
> > from TblA of ServerA , i look at the field's collation which says "database
> > default" and i looked into it which says "SQL Collation"
> > SQL_Latin1_General_CP1_CI_AS
> >
> > so i issued this statement
> > ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
> > collation ?
> >
> > after that statment , shldn't it be changed to Windows Collation -->
> > LATIN_General_BIN ?
> >
> > kindly advise
> >
> > tks & rdgs
> >
> > after i have issued the statement i looked in TblA but the collation is now
> > also "SQL_Latin1_General_CP1_CI_AS"|||> i c but how do i actually change the collation for the indexes now ?
You don't. Drop the index. Change collation for the columns. Create the index.
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"maxzsim" <maxzsim@.discussions.microsoft.com> wrote in message
news:BA2027F4-F137-4014-918F-E9045C55B63F@.microsoft.com...
> Hi ,
> i c but how do i actually change the collation for the indexes now ?
> apprecite ur advice
> tks & rdgs
> "MeanOldDBA" wrote:
>> No. That changes the database collation and any new objects (provided you
>> don't explicitely declare a different collation when you create them) will
>> have that default. You have to issue ALTER statements for every character
>> column though and change each of them. Don't forget about the indexes, which
>> you also have to change.
>> --
>> MeanOldDBA
>> derrickleggett@.hotmail.com
>> http://weblogs.sqlteam.com/derrickl
>> When life gives you a lemon, fire the DBA.
>>
>> "maxzsim" wrote:
>> > Hi,
>> >
>> > I am trying to change the collation of a database
>> >
>> > from TblA of ServerA , i look at the field's collation which says "database
>> > default" and i looked into it which says "SQL Collation"
>> > SQL_Latin1_General_CP1_CI_AS
>> >
>> > so i issued this statement
>> > ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
>> > collation ?
>> >
>> > after that statment , shldn't it be changed to Windows Collation -->
>> > LATIN_General_BIN ?
>> >
>> > kindly advise
>> >
>> > tks & rdgs
>> >
>> > after i have issued the statement i looked in TblA but the collation is now
>> > also "SQL_Latin1_General_CP1_CI_AS"|||Hi,
tks for ur reply
rdgs,
"Tibor Karaszi" wrote:
> > i c but how do i actually change the collation for the indexes now ?
> You don't. Drop the index. Change collation for the columns. Create the index.
> --
> Tibor Karaszi, SQL Server MVP
> http://www.karaszi.com/sqlserver/default.asp
> http://www.solidqualitylearning.com/
> Blog: http://solidqualitylearning.com/blogs/tibor/
>
> "maxzsim" <maxzsim@.discussions.microsoft.com> wrote in message
> news:BA2027F4-F137-4014-918F-E9045C55B63F@.microsoft.com...
> > Hi ,
> >
> > i c but how do i actually change the collation for the indexes now ?
> >
> > apprecite ur advice
> >
> > tks & rdgs
> >
> > "MeanOldDBA" wrote:
> >
> >> No. That changes the database collation and any new objects (provided you
> >> don't explicitely declare a different collation when you create them) will
> >> have that default. You have to issue ALTER statements for every character
> >> column though and change each of them. Don't forget about the indexes, which
> >> you also have to change.
> >> --
> >> MeanOldDBA
> >> derrickleggett@.hotmail.com
> >> http://weblogs.sqlteam.com/derrickl
> >>
> >> When life gives you a lemon, fire the DBA.
> >>
> >>
> >> "maxzsim" wrote:
> >>
> >> > Hi,
> >> >
> >> > I am trying to change the collation of a database
> >> >
> >> > from TblA of ServerA , i look at the field's collation which says "database
> >> > default" and i looked into it which says "SQL Collation"
> >> > SQL_Latin1_General_CP1_CI_AS
> >> >
> >> > so i issued this statement
> >> > ALTER DATABASE dbA COLLATION LATIN_General_BIN --> this shld be a windows
> >> > collation ?
> >> >
> >> > after that statment , shldn't it be changed to Windows Collation -->
> >> > LATIN_General_BIN ?
> >> >
> >> > kindly advise
> >> >
> >> > tks & rdgs
> >> >
> >> > after i have issued the statement i looked in TblA but the collation is now
> >> > also "SQL_Latin1_General_CP1_CI_AS"
>

Monday, March 19, 2012

Collapsible reports

Hi,

I have a Dataset with repetitive data and i want to group all data based on a particular field and have it disaplayed as collapsible rows on a report.

BTW i am generating reports dynamically in my APP.Any ideas on how to proceed?

If I understand correctly, you want to group your data and have the details toggled by the group. To do that, you just need to add a table group on the field, set the visibility properties on the detail row of the table - 1. it's toggled by a textbox in the group header 2. the initial visibility to be hidden if you want to start as collapsed.|||

Hi,

Thanks 4 ur post wang...

You understood my question exactly...

Do u want me to add one more table to the Report?

could you please be more elaborate as to what needs to be done?

|||

No, you don't need another table. Here is a sample report to show how to do this:

<?xml version="1.0" encoding="utf-8"?>
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<DataSources>
<DataSource Name="Northwind">
<DataSourceReference>Northwind</DataSourceReference>
<rd:DataSourceID>30d8ee62-a72d-48fa-ad77-66fdebc3f620</rd:DataSourceID>
</DataSource>
</DataSources>
<BottomMargin>1in</BottomMargin>
<RightMargin>1in</RightMargin>
<rd:DrawGrid>true</rd:DrawGrid>
<InteractiveWidth>8.5in</InteractiveWidth>
<rd:SnapToGrid>true</rd:SnapToGrid>
<Body>
<ReportItems>
<Table Name="table1">
<DataSetName>DataSet1</DataSetName>
<Top>0.625in</Top>
<TableGroups>
<TableGroup>
<Header>
<TableRows>
<TableRow>
<TableCells>
<TableCell>
<ReportItems>
<Textbox Name="textbox6">
<rd:DefaultName>textbox6</rd:DefaultName>
<ZIndex>5</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>=Fields!CategoryID.Value</Value>
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="textbox3">
<rd:DefaultName>textbox3</rd:DefaultName>
<ZIndex>4</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value />
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="textbox4">
<rd:DefaultName>textbox4</rd:DefaultName>
<ZIndex>3</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value />
</Textbox>
</ReportItems>
</TableCell>
</TableCells>
<Height>0.25in</Height>
</TableRow>
</TableRows>
</Header>
<Grouping Name="table1_Group1">
<GroupExpressions>
<GroupExpression>=Fields!CategoryID.Value</GroupExpression>
</GroupExpressions>
</Grouping>
</TableGroup>
</TableGroups>
<Details>
<TableRows>
<TableRow>
<TableCells>
<TableCell>
<ReportItems>
<Textbox Name="textbox7">
<rd:DefaultName>textbox7</rd:DefaultName>
<ZIndex>2</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<TextAlign>Right</TextAlign>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value />
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="ProductName">
<rd:DefaultName>ProductName</rd:DefaultName>
<ZIndex>1</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>=Fields!ProductName.Value</Value>
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="UnitPrice">
<rd:DefaultName>UnitPrice</rd:DefaultName>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<TextAlign>Right</TextAlign>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>=Fields!UnitPrice.Value</Value>
</Textbox>
</ReportItems>
</TableCell>
</TableCells>
<Height>0.25in</Height>
</TableRow>
</TableRows>
<Visibility>
<ToggleItem>textbox6</ToggleItem>
<Hidden>true</Hidden>
</Visibility>
</Details>
<Header>
<TableRows>
<TableRow>
<TableCells>
<TableCell>
<ReportItems>
<Textbox Name="textbox5">
<rd:DefaultName>textbox5</rd:DefaultName>
<ZIndex>8</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<TextAlign>Right</TextAlign>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>Category ID</Value>
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="textbox1">
<rd:DefaultName>textbox1</rd:DefaultName>
<ZIndex>7</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>Product Name</Value>
</Textbox>
</ReportItems>
</TableCell>
<TableCell>
<ReportItems>
<Textbox Name="textbox2">
<rd:DefaultName>textbox2</rd:DefaultName>
<ZIndex>6</ZIndex>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value>Unit Price</Value>
</Textbox>
</ReportItems>
</TableCell>
</TableCells>
<Height>0.25in</Height>
</TableRow>
</TableRows>
</Header>
<TableColumns>
<TableColumn>
<Width>2.16667in</Width>
</TableColumn>
<TableColumn>
<Width>2.16667in</Width>
</TableColumn>
<TableColumn>
<Width>2.16667in</Width>
</TableColumn>
</TableColumns>
<Height>0.75in</Height>
</Table>
</ReportItems>
<Height>3.25in</Height>
</Body>
<rd:ReportID>87afdd90-7b33-49bc-8880-0df212c6637a</rd:ReportID>
<LeftMargin>1in</LeftMargin>
<DataSets>
<DataSet Name="DataSet1">
<Query>
<CommandText>SELECT TOP 10 CategoryID, ProductName, UnitPrice
FROM Products</CommandText>
<DataSourceName>Northwind</DataSourceName>
</Query>
<Fields>
<Field Name="CategoryID">
<rd:TypeName>System.Int32</rd:TypeName>
<DataField>CategoryID</DataField>
</Field>
<Field Name="ProductName">
<rd:TypeName>System.String</rd:TypeName>
<DataField>ProductName</DataField>
</Field>
<Field Name="UnitPrice">
<rd:TypeName>System.Decimal</rd:TypeName>
<DataField>UnitPrice</DataField>
</Field>
</Fields>
</DataSet>
</DataSets>
<Width>6.50001in</Width>
<InteractiveHeight>11in</InteractiveHeight>
<Language>en-US</Language>
<PageFooter>
<Height>0.375in</Height>
<PrintOnLastPage>true</PrintOnLastPage>
<PrintOnFirstPage>true</PrintOnFirstPage>
</PageFooter>
<TopMargin>1in</TopMargin>
</Report>

Sunday, March 11, 2012

Code suggestions for database searches

I have a database containing several tables with many different fields. I need to create an admin section that lets me search on one field or the combination of several. Does anyone have links to pages that offer a general overview for inhouse database search strategy and admin edits.

Thank you

>> I need to create an admin section that lets me search on one field or the combination of several.

Do you means within a given table or across all tables?

>> database search strategy and admin edits

If across all tables, what about validation? A generic edit solution would bypasss data validation checks - not a good idea.

|||I need it across several tables and I am experimenting with the Multi_View control because although it only displays one view at a time all controls are accessible because the Views do not function as seperate containers. So far it seems to be meeting the major requirements however the displays are a little hard to figure out.|||

Have you considered how to handle data validation?

|||

I am doing that using Validation controls on the database submission form and in the View Edit template. At least I expect Validation will work in the Views.

Thursday, March 8, 2012

Code Question - Making a field Null

Hi,
I need to change some code and make a field always show the value NULL
moving forward. I need to keep the field there becuase at the end
result the value will be imported another way.
Currently, the field is coded like this: ISNULL(email_addr,'')
How can I change this to always just be NULL?
Thank you,
RayYou can update the column value to be NULL:
UPDATE MyTable
SET email_addr = NULL;
Then you simply select the column without using ISNULL:
SELECT email_addr
FROM MyTable;
HTH,
Plamen Ratchev
http://www.SQLStudio.com

Code Question - Making a field Null

Hi,
I need to change some code and make a field always show the value NULL
moving forward. I need to keep the field there becuase at the end
result the value will be imported another way.
Currently, the field is coded like this: ISNULL(email_addr,'')
How can I change this to always just be NULL?
Thank you,
Ray
You can update the column value to be NULL:
UPDATE MyTable
SET email_addr = NULL;
Then you simply select the column without using ISNULL:
SELECT email_addr
FROM MyTable;
HTH,
Plamen Ratchev
http://www.SQLStudio.com

Wednesday, March 7, 2012

Coalesce tables?

Hi all,
I'm working with CRM and I need to selectively add one of 5 tables.
Each of these tables have a field called activityid.
I'd like to join only the one with a specific activity ID. Can I do a left
outer join with coalesce?Since coalesce returns the first nonnull expression among its arguments, in
your case it will return first table name only. But I am not able to figure
out why you want tables?
Amarnath
"Ryan" wrote:
> Hi all,
> I'm working with CRM and I need to selectively add one of 5 tables.
> Each of these tables have a field called activityid.
> I'd like to join only the one with a specific activity ID. Can I do a left
> outer join with coalesce?
>
>|||Well I am working with CRM and CRM uses these Filtered views which link in
too many tables. (so many that at some points the report will not run
because too many tables have been linked) Basically there's a central table
that links to 6 other tables, but only successfully links on one of those as
the id from the central table is unique amongst the 6 tables. I was trying
to coalesce this joining so that once it hit the table that has the data it
would stop and not join the rest so that I would not hit my limit of 260
joined tables as I have been.
"Amarnath" <Amarnath@.discussions.microsoft.com> wrote in message
news:C1799839-0E0E-477A-AE16-1BBD98A8F04F@.microsoft.com...
> Since coalesce returns the first nonnull expression among its arguments,
> in
> your case it will return first table name only. But I am not able to
> figure
> out why you want tables?
> Amarnath
> "Ryan" wrote:
>> Hi all,
>> I'm working with CRM and I need to selectively add one of 5 tables.
>> Each of these tables have a field called activityid.
>> I'd like to join only the one with a specific activity ID. Can I do a
>> left
>> outer join with coalesce?
>>

Saturday, February 25, 2012

COALESCE an integer?

Hi guys
I've got a table with a field called PMon_Total. At the moment, a lot have
rows have this set to null.
I want to substitute this NULL for a 0 so that I can count all the
PMon_Total fields, however, I can't get coalesce to work.
Here's my select...
SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions WHE...
Works fine if I try and grab PMon_Total values from C#, as long as they
arent null! However, if I put
SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) FROM
Sessions WHE...
my code give me a System.IndexOutOfRange exception. How can I coalesce
PMon_Total, so I know that any nulls will show as 0?!
Cheers
Dan> I want to substitute this NULL for a 0 so that I can count all the
> PMon_Total fields, however, I can't get coalesce to work.
I'm not sure what this means. Why would counting require you to change
nulls to zero? COUNT(*) will count rows whether NULL or not.

> my code give me a System.IndexOutOfRange exception.
That doesn't look like a SQL Server error. Can you tell us the exact
error message and error number please. Did you try the query in Query
Analyzer? Post some code to reproduce the problem if you can. I suspect
this is a client-side error.
David Portas
SQL Server MVP
--|||try
SELECT ProjectID, SessionID, SessionDate, isnull(PMon_Total,0) FROM
Sessions WHE...
Regards
R.D
--Knowledge gets doubled when shared
"dhnriverside" wrote:

> Hi guys
> I've got a table with a field called PMon_Total. At the moment, a lot have
> rows have this set to null.
> I want to substitute this NULL for a 0 so that I can count all the
> PMon_Total fields, however, I can't get coalesce to work.
> Here's my select...
> SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions WHE...
> Works fine if I try and grab PMon_Total values from C#, as long as they
> arent null! However, if I put
> SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) FROM
> Sessions WHE...
> my code give me a System.IndexOutOfRange exception. How can I coalesce
> PMon_Total, so I know that any nulls will show as 0?!
> Cheers
>
> Dan|||It's weird. I've just tried isnull() and that gave me the error as well.
Here's the C# code I'm using (where sDate = '2005-04-01' and eDate =
'2005-10-13')...
sql = "SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions
WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDate + "')
ORDER BY ProjectID";
SqlConnection dbConn = new
SqlConnection(ConfigurationSettings.AppSettings.Get("System_ConnectionString
"));
dbConn.Open();
SqlCommand prjCmd = new SqlCommand(sql, dbConn);
SqlDataReader prjDr = prjCmd.ExecuteReader();
try
{
while(prjDr.Read())
{
Response.Write(prjDr["ProjectID"].ToString() + ", " +
prjDr["SessionID"].ToString() + ", " + prjDr["SessionDate"].ToString() + "|"
);
if(Convert.ToInt32(prjDr["ProjectID"].ToString()) > projID)
{
projC++;
projID = Convert.ToInt32(prjDR["ProjectID"].ToString());
Response.Write("new!");
}
seshC++;
Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
}
}
finally
{
prjDr.Close();
prjDr = null;
dbConn.Close();
dbConn = null;
}
The response.write statements are purely for debugging :)
Basically, with the code like that, it works perfectly. However, If I try
sql = "SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) FROM
Sessions WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDate
+ "') ORDER BY ProjectID";
or isnull() - i get the following error...
Server Error in '/dartsIntranetV2.1' Application.
----
--
PMon_Total
Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more information abou
t
the error and where it originated in the code.
Exception Details: System.IndexOutOfRangeException: PMon_Total
Source Error:
An unhandled exception was generated during the execution of the current web
request. Information regarding the origin and location of the exception can
be identified using the exception stack trace below.
The error message identifies line 223, which is effectively the last line in
the loop...
Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
Any help much appreciated!
Cheers
Dan
----
"David Portas" wrote:

> I'm not sure what this means. Why would counting require you to change
> nulls to zero? COUNT(*) will count rows whether NULL or not.
>
> That doesn't look like a SQL Server error. Can you tell us the exact
> error message and error number please. Did you try the query in Query
> Analyzer? Post some code to reproduce the problem if you can. I suspect
> this is a client-side error.
> --
> David Portas
> SQL Server MVP
> --
>|||If you print the SQL statement you send to SQL Server (or use Profiler to ca
tch it), you can do two
things:
1. Execute in Query Analyzer to see whether the problem is in the client or
in SQL Server.
2. Post it here so we can have a look at it.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"dhnriverside" <dan@.musoswire.com> wrote in message
news:EE59E12B-A568-4482-95C0-D6E7C67CFE86@.microsoft.com...
> It's weird. I've just tried isnull() and that gave me the error as well.
> Here's the C# code I'm using (where sDate = '2005-04-01' and eDate =
> '2005-10-13')...
> sql = "SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions
> WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDate + "')
> ORDER BY ProjectID";
>
> SqlConnection dbConn = new
> SqlConnection(ConfigurationSettings.AppSettings.Get("System_ConnectionStri
ng"));
> dbConn.Open();
> SqlCommand prjCmd = new SqlCommand(sql, dbConn);
> SqlDataReader prjDr = prjCmd.ExecuteReader();
> try
> {
> while(prjDr.Read())
> {
> Response.Write(prjDr["ProjectID"].ToString() + ", " +
> prjDr["SessionID"].ToString() + ", " + prjDr["SessionDate"].ToString() + "
|");
> if(Convert.ToInt32(prjDr["ProjectID"].ToString()) > projID)
> {
> projC++;
> projID = Convert.ToInt32(prjDR["ProjectID"].ToString());
> Response.Write("new!");
> }
> seshC++;
> Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
> }
> }
> finally
> {
> prjDr.Close();
> prjDr = null;
> dbConn.Close();
> dbConn = null;
> }
> The response.write statements are purely for debugging :)
> Basically, with the code like that, it works perfectly. However, If I try
> sql = "SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) FR
OM
> Sessions WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDa
te
> + "') ORDER BY ProjectID";
> or isnull() - i get the following error...
> Server Error in '/dartsIntranetV2.1' Application.
> ----
--
> PMon_Total
> Description: An unhandled exception occurred during the execution of the
> current web request. Please review the stack trace for more information ab
out
> the error and where it originated in the code.
> Exception Details: System.IndexOutOfRangeException: PMon_Total
> Source Error:
> An unhandled exception was generated during the execution of the current w
eb
> request. Information regarding the origin and location of the exception ca
n
> be identified using the exception stack trace below.
> The error message identifies line 223, which is effectively the last line
in
> the loop...
> Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
> Any help much appreciated!
> Cheers
>
> Dan
> ----
> "David Portas" wrote:
>|||This is a C# error so you may have more luck in a C# forum.
Why aren't you using the parameters collection to pass your parameters?
That at least would eliminate the possibility of a corrupt command
string due to invalid input. It also avoids any SQL injection
vulnerabilities. Example at:
http://msdn.microsoft.com/library/d.../>
ersTopic.asp
You should also consider putting the SQL in a proc since the query
appears to be static anyway.
David Portas
SQL Server MVP
--|||You need to give the column an alias,
SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) AS
PMon_Total FROM
Sessions WHE...
That should fix it - it was being returned to c# with no column name.
"dhnriverside" <dan@.musoswire.com> wrote in message
news:13A0B95A-CBB3-40D3-9FF6-4B6762CB8A6D@.microsoft.com...
> Hi guys
> I've got a table with a field called PMon_Total. At the moment, a lot have
> rows have this set to null.
> I want to substitute this NULL for a 0 so that I can count all the
> PMon_Total fields, however, I can't get coalesce to work.
> Here's my select...
> SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions WHE...
> Works fine if I try and grab PMon_Total values from C#, as long as they
> arent null! However, if I put
> SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0) FROM
> Sessions WHE...
> my code give me a System.IndexOutOfRange exception. How can I coalesce
> PMon_Total, so I know that any nulls will show as 0?!
> Cheers
>
> Dan|||> Basically, with the code like that, it works perfectly. However, If I try
> sql = "SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0)
> FROM
> Sessions WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" +
> eDate
> + "') ORDER BY ProjectID";
> or isnull() - i get the following error...
This SQL statement doesn't include an alias for COALESCE(PMon_Total,0). You
get an IndexOutOfRangeException exception when you reference
prjDr["PMon_Total"] because no column with that name exists in the result.
Try specifying PMon_Total as the alias for the COALESCE expression:
sql = "SELECT ProjectID, SessionID, SessionDate,
COALESCE(PMon_Total,0) AS PMon_Total
FROM Sessions
WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDate
+ "') ORDER BY ProjectID";
Hope this helps.
Dan Guzman
SQL Server MVP
"dhnriverside" <dan@.musoswire.com> wrote in message
news:EE59E12B-A568-4482-95C0-D6E7C67CFE86@.microsoft.com...
> It's weird. I've just tried isnull() and that gave me the error as well.
> Here's the C# code I'm using (where sDate = '2005-04-01' and eDate =
> '2005-10-13')...
> sql = "SELECT ProjectID, SessionID, SessionDate, PMon_Total FROM Sessions
> WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" + eDate + "')
> ORDER BY ProjectID";
>
> SqlConnection dbConn = new
> SqlConnection(ConfigurationSettings.AppSettings.Get("System_ConnectionStri
ng"));
> dbConn.Open();
> SqlCommand prjCmd = new SqlCommand(sql, dbConn);
> SqlDataReader prjDr = prjCmd.ExecuteReader();
> try
> {
> while(prjDr.Read())
> {
> Response.Write(prjDr["ProjectID"].ToString() + ", " +
> prjDr["SessionID"].ToString() + ", " + prjDr["SessionDate"].ToString() +
> "|");
> if(Convert.ToInt32(prjDr["ProjectID"].ToString()) > projID)
> {
> projC++;
> projID = Convert.ToInt32(prjDR["ProjectID"].ToString());
> Response.Write("new!");
> }
> seshC++;
> Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
> }
> }
> finally
> {
> prjDr.Close();
> prjDr = null;
> dbConn.Close();
> dbConn = null;
> }
> The response.write statements are purely for debugging :)
> Basically, with the code like that, it works perfectly. However, If I try
> sql = "SELECT ProjectID, SessionID, SessionDate, COALESCE(PMon_Total,0)
> FROM
> Sessions WHERE (SessionDate > '" + sDate + "') AND (SessionDate < '" +
> eDate
> + "') ORDER BY ProjectID";
> or isnull() - i get the following error...
> Server Error in '/dartsIntranetV2.1' Application.
> ----
--
> PMon_Total
> Description: An unhandled exception occurred during the execution of the
> current web request. Please review the stack trace for more information
> about
> the error and where it originated in the code.
> Exception Details: System.IndexOutOfRangeException: PMon_Total
> Source Error:
> An unhandled exception was generated during the execution of the current
> web
> request. Information regarding the origin and location of the exception
> can
> be identified using the exception stack trace below.
> The error message identifies line 223, which is effectively the last line
> in
> the loop...
> Response.Write(", " + prjDr["PMon_Total"].ToString() + "<br>");
> Any help much appreciated!
> Cheers
>
> Dan
> ----
> "David Portas" wrote:
>|||Fixed!
I had a look at the query code running from Web Data Administrator, and it
was passing the results of COALESCE as a new column, named Column 1.
I changed it to COALESCE(PMon_Total, 0) AS MonTotal, and pulled that from my
code, which works perfectly.
Thanks for everyones help!
"David Portas" wrote:

> This is a C# error so you may have more luck in a C# forum.
> Why aren't you using the parameters collection to pass your parameters?
> That at least would eliminate the possibility of a corrupt command
> string due to invalid input. It also avoids any SQL injection
> vulnerabilities. Example at:
> http://msdn.microsoft.com/library/d...
etersTopic.asp
> You should also consider putting the SQL in a proc since the query
> appears to be static anyway.
> --
> David Portas
> SQL Server MVP
> --
>

Tuesday, February 14, 2012

clustered ix and non on same field

I have a SS 2000 database that was created from a purchased, commercial
software product. I.e. I had no input into the design. This is your typical
OLTP and DSS database. I notice on many tables that there is a clustered
index and non-clustered index on the same column. I feel like this is a
mistake and I should delete every non-clustered index that has a clustered
index, assuming the clustered index is the primary key. Is it ever
advantageous to have both a CIX and nonCIX on the same field so that the
optimizer can use one for range/sorts (CIX) and the other for single record
lookup (nonCIX)?
TIA - nick
The only case I can think of is when the NC covers the query and you have low selectivity. SQL
Server can now read the NS index pages only which will be fewer pages than the CL pages for the
corresponding data-range over the column. However, I suspect that this is the PK and possibly even
some surrogate key, so an NC index on this column will probably not cover that many queries.
I've seen stranger things with commercial software databases... :-)
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Nick" <Nick@.discussions.microsoft.com> wrote in message
news:31AC2451-7141-4573-8E4D-C3E87FCA9623@.microsoft.com...
>I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typical
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single record
> lookup (nonCIX)?
> TIA - nick
|||In addition to Tibor's reply: such an index can also help if there is no
other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
I would consider it a bad practice to blindly add a nonclustered index
of the clustered index to each and every table. Only if a query like the
mentioned examples are very important (above average) one could
incidentally consider such an extra index. Otherwise, it is mostly
wasting space and adding overhead for index maintenance.
Gert-Jan
Nick wrote:
> I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typical
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single record
> lookup (nonCIX)?
> TIA - nick
|||> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
which is a case where the index covers the query, but possibly an important example worth pointing
out explicitly. :-)
Also, it can be worth to mention that any NC index will cover above query, and probably SQL Server
will pick the NC index over the most narrow column.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467AEDBF.806A445F@.toomuchspamalready.nl...[vbcol=seagreen]
> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
> I would consider it a bad practice to blindly add a nonclustered index
> of the clustered index to each and every table. Only if a query like the
> mentioned examples are very important (above average) one could
> incidentally consider such an extra index. Otherwise, it is mostly
> wasting space and adding overhead for index maintenance.
> Gert-Jan
>
> Nick wrote:
|||Tibor Karaszi wrote:
>
> which is a case where the index covers the query, but possibly an important example worth pointing
> out explicitly. :-)
> Also, it can be worth to mention that any NC index will cover above query, and probably SQL Server
> will pick the NC index over the most narrow column.
Yes, and this is a somewhat interesting, because the NC index that
matches the clustered index will (by definition) always be the
narrowest, because the clustered key is part of any nonclustered index
key. So for SELECT COUNT(*) FROM the_table, this type of index is
perfect (however small the difference with another NC index).
Gert-Jan
|||> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest,
How true, Gert-Jan.
Good catch, an easy thing to overlook (just as I did). :-)
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467BF4AB.FB8F8F07@.toomuchspamalready.nl...
> Tibor Karaszi wrote:
> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest, because the clustered key is part of any nonclustered index
> key. So for SELECT COUNT(*) FROM the_table, this type of index is
> perfect (however small the difference with another NC index).
> Gert-Jan

clustered ix and non on same field

I have a SS 2000 database that was created from a purchased, commercial
software product. I.e. I had no input into the design. This is your typical
OLTP and DSS database. I notice on many tables that there is a clustered
index and non-clustered index on the same column. I feel like this is a
mistake and I should delete every non-clustered index that has a clustered
index, assuming the clustered index is the primary key. Is it ever
advantageous to have both a CIX and nonCIX on the same field so that the
optimizer can use one for range/sorts (CIX) and the other for single record
lookup (nonCIX)?
TIA - nickThe only case I can think of is when the NC covers the query and you have lo
w selectivity. SQL
Server can now read the NS index pages only which will be fewer pages than t
he CL pages for the
corresponding data-range over the column. However, I suspect that this is th
e PK and possibly even
some surrogate key, so an NC index on this column will probably not cover th
at many queries.
I've seen stranger things with commercial software databases... :-)
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Nick" <Nick@.discussions.microsoft.com> wrote in message
news:31AC2451-7141-4573-8E4D-C3E87FCA9623@.microsoft.com...
>I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typic
al
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single recor
d
> lookup (nonCIX)?
> TIA - nick|||In addition to Tibor's reply: such an index can also help if there is no
other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
I would consider it a bad practice to blindly add a nonclustered index
of the clustered index to each and every table. Only if a query like the
mentioned examples are very important (above average) one could
incidentally consider such an extra index. Otherwise, it is mostly
wasting space and adding overhead for index maintenance.
Gert-Jan
Nick wrote:
> I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typic
al
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single recor
d
> lookup (nonCIX)?
> TIA - nick|||> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
which is a case where the index covers the query, but possibly an important
example worth pointing
out explicitly. :-)
Also, it can be worth to mention that any NC index will cover above query, a
nd probably SQL Server
will pick the NC index over the most narrow column.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467AEDBF.806A445F@.toomuchspamalready.nl...[vbcol=seagreen]
> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
> I would consider it a bad practice to blindly add a nonclustered index
> of the clustered index to each and every table. Only if a query like the
> mentioned examples are very important (above average) one could
> incidentally consider such an extra index. Otherwise, it is mostly
> wasting space and adding overhead for index maintenance.
> Gert-Jan
>
> Nick wrote:|||Tibor Karaszi wrote:
>
> which is a case where the index covers the query, but possibly an importan
t example worth pointing
> out explicitly. :-)
> Also, it can be worth to mention that any NC index will cover above query,
and probably SQL Server
> will pick the NC index over the most narrow column.
Yes, and this is a somewhat interesting, because the NC index that
matches the clustered index will (by definition) always be the
narrowest, because the clustered key is part of any nonclustered index
key. So for SELECT COUNT(*) FROM the_table, this type of index is
perfect (however small the difference with another NC index).
Gert-Jan|||> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest,
How true, Gert-Jan.
Good catch, an easy thing to overlook (just as I did). :-)
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467BF4AB.FB8F8F07@.toomuchspamalready.nl...
> Tibor Karaszi wrote:
> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest, because the clustered key is part of any nonclustered index
> key. So for SELECT COUNT(*) FROM the_table, this type of index is
> perfect (however small the difference with another NC index).
> Gert-Jan

clustered ix and non on same field

I have a SS 2000 database that was created from a purchased, commercial
software product. I.e. I had no input into the design. This is your typical
OLTP and DSS database. I notice on many tables that there is a clustered
index and non-clustered index on the same column. I feel like this is a
mistake and I should delete every non-clustered index that has a clustered
index, assuming the clustered index is the primary key. Is it ever
advantageous to have both a CIX and nonCIX on the same field so that the
optimizer can use one for range/sorts (CIX) and the other for single record
lookup (nonCIX)?
TIA - nickThe only case I can think of is when the NC covers the query and you have low selectivity. SQL
Server can now read the NS index pages only which will be fewer pages than the CL pages for the
corresponding data-range over the column. However, I suspect that this is the PK and possibly even
some surrogate key, so an NC index on this column will probably not cover that many queries.
I've seen stranger things with commercial software databases... :-)
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Nick" <Nick@.discussions.microsoft.com> wrote in message
news:31AC2451-7141-4573-8E4D-C3E87FCA9623@.microsoft.com...
>I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typical
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single record
> lookup (nonCIX)?
> TIA - nick|||In addition to Tibor's reply: such an index can also help if there is no
other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
I would consider it a bad practice to blindly add a nonclustered index
of the clustered index to each and every table. Only if a query like the
mentioned examples are very important (above average) one could
incidentally consider such an extra index. Otherwise, it is mostly
wasting space and adding overhead for index maintenance.
Gert-Jan
Nick wrote:
> I have a SS 2000 database that was created from a purchased, commercial
> software product. I.e. I had no input into the design. This is your typical
> OLTP and DSS database. I notice on many tables that there is a clustered
> index and non-clustered index on the same column. I feel like this is a
> mistake and I should delete every non-clustered index that has a clustered
> index, assuming the clustered index is the primary key. Is it ever
> advantageous to have both a CIX and nonCIX on the same field so that the
> optimizer can use one for range/sorts (CIX) and the other for single record
> lookup (nonCIX)?
> TIA - nick|||> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
which is a case where the index covers the query, but possibly an important example worth pointing
out explicitly. :-)
Also, it can be worth to mention that any NC index will cover above query, and probably SQL Server
will pick the NC index over the most narrow column.
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467AEDBF.806A445F@.toomuchspamalready.nl...
> In addition to Tibor's reply: such an index can also help if there is no
> other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
> I would consider it a bad practice to blindly add a nonclustered index
> of the clustered index to each and every table. Only if a query like the
> mentioned examples are very important (above average) one could
> incidentally consider such an extra index. Otherwise, it is mostly
> wasting space and adding overhead for index maintenance.
> Gert-Jan
>
> Nick wrote:
>> I have a SS 2000 database that was created from a purchased, commercial
>> software product. I.e. I had no input into the design. This is your typical
>> OLTP and DSS database. I notice on many tables that there is a clustered
>> index and non-clustered index on the same column. I feel like this is a
>> mistake and I should delete every non-clustered index that has a clustered
>> index, assuming the clustered index is the primary key. Is it ever
>> advantageous to have both a CIX and nonCIX on the same field so that the
>> optimizer can use one for range/sorts (CIX) and the other for single record
>> lookup (nonCIX)?
>> TIA - nick|||Tibor Karaszi wrote:
> > In addition to Tibor's reply: such an index can also help if there is no
> > other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
> which is a case where the index covers the query, but possibly an important example worth pointing
> out explicitly. :-)
> Also, it can be worth to mention that any NC index will cover above query, and probably SQL Server
> will pick the NC index over the most narrow column.
Yes, and this is a somewhat interesting, because the NC index that
matches the clustered index will (by definition) always be the
narrowest, because the clustered key is part of any nonclustered index
key. So for SELECT COUNT(*) FROM the_table, this type of index is
perfect (however small the difference with another NC index).
Gert-Jan|||> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest,
How true, Gert-Jan.
Good catch, an easy thing to overlook (just as I did). :-)
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://sqlblog.com/blogs/tibor_karaszi
"Gert-Jan Strik" <sorry@.toomuchspamalready.nl> wrote in message
news:467BF4AB.FB8F8F07@.toomuchspamalready.nl...
> Tibor Karaszi wrote:
>> > In addition to Tibor's reply: such an index can also help if there is no
>> > other nonclustered index and there is a SELECT COUNT(*) FROM the_table.
>> which is a case where the index covers the query, but possibly an important example worth
>> pointing
>> out explicitly. :-)
>> Also, it can be worth to mention that any NC index will cover above query, and probably SQL
>> Server
>> will pick the NC index over the most narrow column.
> Yes, and this is a somewhat interesting, because the NC index that
> matches the clustered index will (by definition) always be the
> narrowest, because the clustered key is part of any nonclustered index
> key. So for SELECT COUNT(*) FROM the_table, this type of index is
> perfect (however small the difference with another NC index).
> Gert-Jan

Clustered Indexes - High or Low Selectivity?

Hi,

I am studying for MCTS and through some of the course material it recommends that a low selectivity field i.e. First Name is a good canditate for a clustered index.

This goes against what is recommended online (completely the opposite) and goes against what I have been taught in the past.

What is correct for the exam?

Thanks

I often find various printed 'study' media with errors. Mark this one as just that.

Indexes, both clustered and non-clustered, may lose their effectiveness when selectivity becomes too low. The Query Processor may ignore a low selectivity index.

Sunday, February 12, 2012

CLUSTERED INDEX or NONCLUSTERED

I have 3 table A, B, C

Table A (15 field, 4 fields indexed and Primary Key) approximate rows: 50.000 60.000

Table B (18 field, 6 fields indexed and Primary Key) approximate rows: 350.000 500.000

Table C (16 filed, 9 fields indexed and Primary Key) approximate rows: 500.000 1.000.000

Structure is something like this:
A (master) --> B (detail) --> C (sub detail)

On each 3 table is added new record, in table C the record is added after a search in table B.
My question is: Which is the best method? CLUSTERED INDEX or NONCLUSTERED INDEX

Thanks
Sorry for my englishIt is not clear about relations between tables (number of fields, etc.) by anyway clustered index for PK and nonclustered for others will be OK.|||Not enough info, these links may help you:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsqlmag01/html/TuningofaDifferentSort.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/createdb/cm_8_des_05_5h6b.asp|||Thank you for your answer.
The diagram is attached, form left to right table A; B; C|||The diagram|||Still not enough info. Some questions:

What is your ratio of inserts to queries? Are you heavy insert or heavy queries or both?

What is typically used for your select criterias?

I would reccomend you start with reading those articles and you may play around with "set statistics IO on" to evaluate your logical IO when you have added a clustered index, taken it off, added a nonclustered index, etc. This to me is the best advice to become self sufficient on indexing questions.

HTH

Clustered index on Identity field

Hi All,
I have heard that if you create a clustered index on identity column(PK
also) it would decrease the page splits. But how?
Thanks,
PradeepIt will eliminate page splits on inserts since all new rows get appended to
the end of the current page. It does not stop pagespilts due to updates on
existing rows on columns with variable lengths. But in any case that should
not be your sole motivation for where you place the Clustered Index. You can
also avoid or minimize page splits with a proper fill factor.
Andrew J. Kelly SQL MVP
"Pradeep Kutty" <pradeepk@.healthasyst.com> wrote in message
news:eW2tO%23HtFHA.2656@.TK2MSFTNGP10.phx.gbl...
> Hi All,
> I have heard that if you create a clustered index on identity column(PK
> also) it would decrease the page splits. But how?
> Thanks,
> Pradeep
>

Clustered Index on Date Field or Identity Field ....

Hi All,
I have a table (detail table) with fields ID (Identity) primary Key and a DT
TM datetime field which is a heap.
Right now there is a non clustered index on ID which is used to join with it
s master table.
I have many reports which uses this table and for all the reports the basic
criteria is between DTTM.
say I run the report for say for a date range of 1 month, 1 w or so.
Im planning to add a clustered index on DTTM field so that the reports would
become faster compared to a table scan what its doing now.
My question is, is it a good idea to create a clustered index on a Datetime
field?
or is it a better way to make ID the clustered index and then create a non c
lustered index on DTTM?
But I always had the doubt that, what is the purpose of creating a clustered
index on an identity field that too which is already a primary key,
since an identity field is already ordered. Does it make sense to create a c
lustered in index on Identity field.
Add to this most of my Stored procedures which are used to retrieve uses ID
to join with its master table.
DTTM would be used only in reports...
Thanks,
PradPradeep Kutty wrote:
> Hi All,
> I have a table (detail table) with fields ID (Identity) primary Key and
> a DTTM datetime field which is a heap.
> Right now there is a non clustered index on ID which is used to join
> with its master table.
> I have many reports which uses this table and for all the reports the
> basic criteria is between DTTM.
> say I run the report for say for a date range of 1 month, 1 w or so.
> Im planning to add a clustered index on DTTM field so that the reports
> would become faster compared to a table scan what its doing now.
> My question is, is it a good idea to create a clustered index on a
> Datetime field?
> or is it a better way to make ID the clustered index and then create a
> non clustered index on DTTM?
> But I always had the doubt that, what is the purpose of creating a
> clustered index on an identity field that too which is already a primary
> key,
> since an identity field is already ordered. Does it make sense to create
> a clustered in index on Identity field.
> Add to this most of my Stored procedures which are used to retrieve uses
> ID to join with its master table.
> DTTM would be used only in reports...
> Thanks,
> Prad
>
it seems that a clustered index is better. try both ways and look at the
execution plan(s)|||Pradeep,

>Im planning to add a clustered index on DTTM field so that the reports would become
faster compared to a table scan what its doing now.
Thats a good idea because clustered index is ideal for range search.

>But I always had the doubt that, what is the purpose of creating a clustere
d index on an identity field that too which is already a primary key,
>since an identity field is already ordered. Does it make sense to create a clustere
d in index on Identity field.
One advantage of having a clustered index on the IDENTITY column is that it
will help you avoid page split problems.
But your assumption about the order of IDENTITY value is wrong. IDENTITY onl
oy provides a logical sequence, whereas a clustered index
controls the order in which the rows are physically stored.
--
Roji. P. Thomas
Net Asset Management
http://toponewithties.blogspot.com
"Pradeep Kutty" <pradeepk@.healthasyst.com> wrote in message news:%23EVpg8TrF
HA.716@.TK2MSFTNGP10.phx.gbl...
Hi All,
I have a table (detail table) with fields ID (Identity) primary Key and a DT
TM datetime field which is a heap.
Right now there is a non clustered index on ID which is used to join with it
s master table.
I have many reports which uses this table and for all the reports the basic
criteria is between DTTM.
say I run the report for say for a date range of 1 month, 1 w or so.
Im planning to add a clustered index on DTTM field so that the reports would
become faster compared to a table scan what its doing now.
My question is, is it a good idea to create a clustered index on a Datetime
field?
or is it a better way to make ID the clustered index and then create a non c
lustered index on DTTM?
But I always had the doubt that, what is the purpose of creating a clustered
index on an identity field that too which is already a primary key,
since an identity field is already ordered. Does it make sense to create a c
lustered in index on Identity field.
Add to this most of my Stored procedures which are used to retrieve uses ID
to join with its master table.
DTTM would be used only in reports...
Thanks,
Prad|||One note of caution (playing devil's advocate here).
I don't know how many people you have updating your table or the hardware yo
u use but...
...one problem with clustered indexes based on the ID is that all WRITES mu
st occur on the same place on the disk, or on the same disk if you're using
an array of disks...everyone's writing data to a new row that goes in after
the last row.
If you have a huge number of updates occurring (which you probably don't) th
en this can cause a problem as you effectively get a "hot spot" on the disk
where everyone is attempting to write to the same part of the disk. Compare
this to a clustered index on (say) the surname, where new rows are added to
different parts of the disk (or on different disks in an array of disks).
Griff
"Pradeep Kutty" <pradeepk@.healthasyst.com> wrote in message news:%23EVpg8TrF
HA.716@.TK2MSFTNGP10.phx.gbl...
Hi All,
I have a table (detail table) with fields ID (Identity) primary Key and a DT
TM datetime field which is a heap.
Right now there is a non clustered index on ID which is used to join with it
s master table.
I have many reports which uses this table and for all the reports the basic
criteria is between DTTM.
say I run the report for say for a date range of 1 month, 1 w or so.
Im planning to add a clustered index on DTTM field so that the reports would
become faster compared to a table scan what its doing now.
My question is, is it a good idea to create a clustered index on a Datetime
field?
or is it a better way to make ID the clustered index and then create a non c
lustered index on DTTM?
But I always had the doubt that, what is the purpose of creating a clustered
index on an identity field that too which is already a primary key,
since an identity field is already ordered. Does it make sense to create a c
lustered in index on Identity field.
Add to this most of my Stored procedures which are used to retrieve uses ID
to join with its master table.
DTTM would be used only in reports...
Thanks,
Prad|||If it is used in joins, then I would put the clustered index on the IDENTITY
column. This can speed up inserts into this table, inserts into related ta
bles, and joins between this table and related tables. If the order of the
IDENTITY increment matches the order of the clustered index on the IDENTITY
column, then all inserts will occur at the end of the table, which minimizes
the required index maintenance operations.
If a table has a clustered index, then all nonclustered indexes use the clus
tered index key to locate rows in the table. If you put a nonclustered inde
x on the primary key, then every join will result in an additional step in t
he execution plan--a bookmark lookup. This extra level of indirection can s
ignificantly reduce the performance of every join. In addition, if you use
a clustered index on a datetime column, and the datetime column is not a can
didate key, then SQL Server will add a 4-byte uniqifier to every index row s
o that the index key can be used in nonclustered indexes to locate rows. Th
is increases the size of each nonclustered index, and can further reduce que
ry performance, especially with respect to joins.
To boost performance for reporting, you have other options aside from simply
adding an index. Here are a couple: (1) use a covering index so that the b
ookmark lookup will not be necessary, or (2) create an indexed view, and use
both the datetime and the identity column (in that order) as the clustered
index key for the view. If all of the columns necessary for the query exist
in the index key, then there is no need for SQL Server to access the actual
data row, so the performance degradation resulting from the use a noncluste
red index will be minimized. If that doesn't provide adequate reporting per
formance, the indexed view option will at least meet the select performance
of accessing a table with a clustered index directly, without degrading the
performance of the joins. It should be noted, however, that insert performa
nce will be degraded by the addition of any index or indexed view.
"Pradeep Kutty" <pradeepk@.healthasyst.com> wrote in message news:#EVpg8TrFHA
.716@.TK2MSFTNGP10.phx.gbl...
Hi All,
I have a table (detail table) with fields ID (Identity) primary Key and a DT
TM datetime field which is a heap.
Right now there is a non clustered index on ID which is used to join with it
s master table.
I have many reports which uses this table and for all the reports the basic
criteria is between DTTM.
say I run the report for say for a date range of 1 month, 1 w or so.
Im planning to add a clustered index on DTTM field so that the reports would
become faster compared to a table scan what its doing now.
My question is, is it a good idea to create a clustered index on a Datetime
field?
or is it a better way to make ID the clustered index and then create a non c
lustered index on DTTM?
But I always had the doubt that, what is the purpose of creating a clustered
index on an identity field that too which is already a primary key,
since an identity field is already ordered. Does it make sense to create a c
lustered in index on Identity field.
Add to this most of my Stored procedures which are used to retrieve uses ID
to join with its master table.
DTTM would be used only in reports...
Thanks,
Prad|||Pradeep Kutty wrote:
> Hi All,
> I have a table (detail table) with fields ID (Identity) primary Key
> and a DTTM datetime field which is a heap.
> Right now there is a non clustered index on ID which is used to join
> with its master table.
> I have many reports which uses this table and for all the reports the
> basic criteria is between DTTM.
> say I run the report for say for a date range of 1 month, 1 w or
> so.
> Im planning to add a clustered index on DTTM field so that the
> reports would become faster compared to a table scan what its doing
> now.
> My question is, is it a good idea to create a clustered index on a
> Datetime field?
> or is it a better way to make ID the clustered index and then create
> a non clustered index on DTTM?
> But I always had the doubt that, what is the purpose of creating a
> clustered index on an identity field that too which is already a
> primary key,
> since an identity field is already ordered. Does it make sense to
> create a clustered in index on Identity field.
> Add to this most of my Stored procedures which are used to retrieve
> uses ID to join with its master table.
> DTTM would be used only in reports...
Either I overlooked it or nobody actually mentioned a composite index. If
you always do queries that join by your PK and use only a date range then
a composite clustered index on (timestamp, ID) might also be worth
considering. Or am I missing something here?
Kind regards
robert

clustered index on a identity field

Hi All,
I have heard that if you create a clustered index on a identity field and
its a PK, it reduces the page splits...
But how?
Thanks,
Pradif you mean that the number of pages required to define a table will
grow more slowly, that is correct. but there are many reasons not to do
this. in my experience, clustering any primary key is a pretty bad
idea, especially an identity column. the reasons are twofold:
1) clustering ensures that all like values will be ordered together. if
you apply this to a value that is gauranteed to be unique, all you are
accomplishing is gauranteeing the physical order of the rows on disk,
which would serve no real purpose (i.e. none of your apps should care
what order the rows are on disk).
in my opinion, you should reserve a clustered index for a column that
has non-unique values, and is often used as a search criteria by value.
that way, all of the rows with the same value are physically grouped
together, greatly improving the performance of the disk read to collect
all the data.
2) creating a clustered index on an identity column is very likely to
create insert hotspots, because it is gauranteed that almost every new
row will be written to the same datapage. if you have a large number of
inserts occurring, this can create lock issues, if the current
insertion page is locked for any reason from insertion. it's far
healthier if your database can insert rows into a nicely dispersed set
of data pages, to prevent issues of lock escalation impeding inserts.
anyway, those are just my two cents. i'm sure other people have other
opinions.|||See if this helps:
Tips on Optimizing SQL Server Clustered Indexes
http://www.sql-server-performance.c...red_indexes.asp
AMB
"Pradeep Kutty" wrote:

> Hi All,
> I have heard that if you create a clustered index on a identity field and
> its a PK, it reduces the page splits...
> But how?
> Thanks,
> Prad
>
>|||Can you fix your clock?
"Pradeep Kutty" <pradeepk@.healthasyst.com> wrote in message
news:eCh33%23HtFHA.616@.TK2MSFTNGP11.phx.gbl...
> Hi All,
> I have heard that if you create a clustered index on a identity field and
> its a PK, it reduces the page splits...
> But how?
> Thanks,
> Prad
>|||I disagree.
The physical location on disk of index rows in a clustered index is
undefined. There is no guarantee that the index pages of a clustered index
reside in any specified order on the physical hardware. What is defined is
that the rows within a specific leaf page are in order, and each clustered
index leaf page contains next and previous pointers to locate the next and
previous leaf pages. One of the main benefits of using a clustered index is
that once the first row in an ordered scan is found, SQL Server doesn't need
to walk the b-tree to find the next row. It can use the next pointer to
continue the ordered scan. This can improve query performance considerably.
You should avoid using a non-unique key in a clustered index. If a table
has a clustered index, then every nonclustered index uses the clustered
index key to locate the row in the table. If the key of a clustered index
is not unique, then SQL Server adds a hidden 4-byte uniquifier to the key to
make it unique. The entire key along with the uniqifier is then stored in
every nonclustered index row.
In addition, there is a significant degradation of join performance. If you
put a nonclustered index on the primary key, then every join with related
tables requires an additional lookup to satisfy the query. For each row,
the index for the primary key constraint is consulted yielding the clustered
index key. That key is then used to lookup the row in the clustered index.
Therefore, if you have related tables, then the clustered index should live
on the primary key.
Your assertion about insert hotspots fails to mention the additional index
maintenance (page splits and updates) that is required if your clustered
index isn't on the IDENTITY column. If the clustered index is on an
IDENTITY column, then there will never be any page splits, because inserts
become appends, both in the b-tree index nodes and in the leaf nodes. You
can also use a 100% fillfactor, because there will never be any inserts,
only appends. The tree grows up: at each level of the b-tree, a new page is
appended if it is needed, and if a new page is needed at the root level,
then a new root page is also added. That's why inserts into a table with
only a clustered index on the IDENTITY column perform almost as well as
inserts into a table without any indexes at all. Deletes and updates in
this case require minimal index maintenance, because SQL Server doesn't join
index pages, it only splits them when an insert exceeds the fillfactor
threshold. Deletes just leave holes, so if you expect a lot of deletes,
then you should schedule a periodic DBCC INDEXDEFRAG or DBCC DBREINDEX.
SQL Server uses lazy spooling, which means that changes to the database are
cached and then periodically flushed to disk (checkpointed). (SQL Server
only ensures that writes to the transaction log are flushed to disk before
returning from a commit.) This means that more often than not, the last
page is still resident in memory if there are a large number of inserts,
thereby turning the insert hotspot into a performance improvement.
Finally, unless otherwise forced, the exclusive locks applied by an insert
should not escalate unless the page is full and all of the rows in the page
were just inserted by the current transaction. Therefore, there is little
if any lock contention due to inserts.
"jason" <iaesun@.yahoo.com> wrote in message
news:1126190553.831020.325290@.f14g2000cwb.googlegroups.com...
> if you mean that the number of pages required to define a table will
> grow more slowly, that is correct. but there are many reasons not to do
> this. in my experience, clustering any primary key is a pretty bad
> idea, especially an identity column. the reasons are twofold:
> 1) clustering ensures that all like values will be ordered together. if
> you apply this to a value that is gauranteed to be unique, all you are
> accomplishing is gauranteeing the physical order of the rows on disk,
> which would serve no real purpose (i.e. none of your apps should care
> what order the rows are on disk).
> in my opinion, you should reserve a clustered index for a column that
> has non-unique values, and is often used as a search criteria by value.
> that way, all of the rows with the same value are physically grouped
> together, greatly improving the performance of the disk read to collect
> all the data.
> 2) creating a clustered index on an identity column is very likely to
> create insert hotspots, because it is gauranteed that almost every new
> row will be written to the same datapage. if you have a large number of
> inserts occurring, this can create lock issues, if the current
> insertion page is locked for any reason from insertion. it's far
> healthier if your database can insert rows into a nicely dispersed set
> of data pages, to prevent issues of lock escalation impeding inserts.
> anyway, those are just my two cents. i'm sure other people have other
> opinions.
>|||jason wrote:
> if you mean that the number of pages required to define a table will
> grow more slowly, that is correct. but there are many reasons not to
> do this. in my experience, clustering any primary key is a pretty bad
> idea, especially an identity column. the reasons are twofold:
> 1) clustering ensures that all like values will be ordered together.
> if you apply this to a value that is gauranteed to be unique, all you
> are accomplishing is gauranteeing the physical order of the rows on
> disk, which would serve no real purpose (i.e. none of your apps
> should care what order the rows are on disk).
> in my opinion, you should reserve a clustered index for a column that
> has non-unique values, and is often used as a search criteria by
> value. that way, all of the rows with the same value are physically
> grouped together, greatly improving the performance of the disk read
> to collect all the data.
> 2) creating a clustered index on an identity column is very likely to
> create insert hotspots, because it is gauranteed that almost every new
> row will be written to the same datapage. if you have a large number
> of inserts occurring, this can create lock issues, if the current
> insertion page is locked for any reason from insertion. it's far
> healthier if your database can insert rows into a nicely dispersed set
> of data pages, to prevent issues of lock escalation impeding inserts.
> anyway, those are just my two cents. i'm sure other people have other
> opinions.
I would like to comment on some of what you wrote. Clustering on a
non-unique columns has a few implications.
- SQL Server cannot handle non-unique clustered keys internally and will
automatically add a UNIQUEIDENTIFIER to the rows when necessary. This
increases the key length by 4-bytes for each non-unique value. Using an
IDENTITY value, which is by definition unique, does not have this added
overhead.
- The clustered index key is the pointer into the actual data.
Therefore, the clustered index key is a part of each non-clustered index
key. This can make the non-clustered indexes grow considerably. Given
that using a non-unique set of columns is likely to include at least one
non-integer based column, you are looking at large keys all around. This
will slow down inserting and updating because of the need to hit each
non-clustered index. Clustered IDENTITY columns add the least amount of
overhead to non-clustered indexes.
- A non-unique clustered index key is likely to be more susceptible to
updating. Updating a clustered index key means physically moving the row
to a new location and this will likely cause page splitting, which is a
slow process that causes internal fragmentation. This will slow down
inserting and updating because of the need to locate/relocate the row
and the need to update each non-clustered index key. IDENTITY columns
cannot be updated and are immune to this problem.
- Insert hotspots aren't really a problem any longer like they were in
the old day of page locking. SQL Server uses row locking for inserts.
Keeping the disk heads from moving around can actually increase
performance because of the slow nature of the hard drive. Using an
IDENTITY keeps the disk heads in the same location and prevents page
splitting as new rows are added.
- A non-unique clustered index may require additional maintenance to
avoid page splitting. That is, you may have to implement index rebuilds
using a FILLFACTOR that leaves a certain amount of space available for
inserts on each page. The maintenance is ongoing and is best done during
off-hours; assuming your business has off-hours. This increases the
table size and number of pages and will hurt overall performance.
- Page splitting causes external fragmentation. That is, even if you use
a clustered index on a set of non-unique columns, there's no reason to
assume that pages that contain the same key will be contiguous. So a
read of two pages of a specific clustered index key can cause the disk
heads to move from one end of the table to another. This can be avoided
with some index maintenance. Clustered IDENTITY indexes do not have this
problem.
Having said that, there are reasons to use non-unique clustered indexes.
As you stated, they can, in fact, help the fetching of a number of rows
of a specific key. If your database is used primarily for this type of
operation, a non-unique clustered index may be the way to go. I've
certainly used them this way on many occasions.
David Gugick
Quest Software
www.imceda.com
www.quest.com|||interesting, you clearly have some well informed opinions. they just
happen to disagree with some of the sources i've used to come to my
understanding :) these things happen. i admit, my understanding of
clustered indexing, and indexing in general, is incomplete, but here
are some points that i thought i'd share, to see if perhaps there's an
absolute answer:
* from every text at my disposal, the primary advantage to a clustered
index is the fact that the data is guaranteed to be in the same order
as the index.
* the leaf nodes of a clustered index don't actually point to the next
and previous rows, because they don't have to. the next and previous
values are implied by the next and previous positions on disk.
* nonclustered indexes do point to next and previous data rows, because
the index order may not match the physical order, so a pointer is
required
* the greatest advantages to using clustered indexes, therefore, are
cases where the physical order of the data can increase your
performance. chief among these are (1) columns commonly used in group
by and order by clauses (2) columns on the many side of a one-to-many
relationship. because there is a tremendous increase to the performance
of the reads for these operations (3) columns whose values are
frequently evaluated between a range
* by the same reasoning, clustered indexes are wasted on unique value
columns, as they serve no tangible purpose (except as you mention,
perhaps ameliorating problems using identity columns without a
clustered index)
* using a clustered index on a unique value is wasted. the only reason
is the default for new tables created in enterprise manager is because
it grants advantages to some queries above a table that has zero
clustered indexes (better one than none)
here are my sources for this information:
microsoft sql server 2000 bible, paul nielsen, pp768-771
sql server 2000 for experienced dba's, brian knight, pp252-255
http://msdn.microsoft.com/library/d...ql7perftune.asp
http://msdn.microsoft.com/library/d...br />
apr3.asp
these sources cite specific examples of where and why you would want to
use clustered indexes, and they are all on data that is grouped by,
sorted by, or evaluated in a range. especially date fields (which are
rarely unique, yes?)
one caveat that is mentioned is that you shouldn't apply a clustered
index to a column that is updated often, for the reason you stated,
that the clustered index is appended to every nonclustered index in the
table. but you cite this as a performance hindrance? my undrestanding
is that the presence of the clustered index is actually increasing
performance (if at a small cost of space) by skipping the pointer to
data page step of a lookup.
what are your sources, that we might compare / contrast?
jason|||"jason" <iaesun@.yahoo.com> wrote in message
news:1126206276.049357.153630@.g43g2000cwa.googlegroups.com...
> interesting, you clearly have some well informed opinions. they just
> happen to disagree with some of the sources i've used to come to my
> understanding :) these things happen. i admit, my understanding of
> clustered indexing, and indexing in general, is incomplete, but here
> are some points that i thought i'd share, to see if perhaps there's an
> absolute answer:
> * from every text at my disposal, the primary advantage to a clustered
> index is the fact that the data is guaranteed to be in the same order
> as the index.
>
And the clustered index requires one fewer IO per s since the leaf is the
data page; plus s performance of all non-clustered indexes requires 1-4
extra IO's.

> * the leaf nodes of a clustered index don't actually point to the next
> and previous rows, because they don't have to. the next and previous
> values are implied by the next and previous positions on disk.
>
No. The leaf nodes are data pages. All data pages in a table are arranged
in a doubly linked list: each page has a next page and previous page
pointer. A table scan traverses the table by following the next/previous
pointers from page to page. For a table with a clustered index the order of
rows on a page and the order of pages determined by the next/previous
pointers follow the order of the index. So after you traverse the index
down to the leaf level once you can then follow the next/previous pointers
to follow the index order. So you don't have to go back to the index pages
to satisfy a range query: just s to the first value and the scan to the
end.
A common misconception is that data pages in a clustered index are
guaranteed to be physically ordered. They are not. Only the logical order
of the doubly-linked list of data pages is guaranteed. Difference between
the logical ordering of the pages and the physical order can arise over time
due to index fragmentation.

> * nonclustered indexes do point to next and previous data rows, because
> the index order may not match the physical order, so a pointer is
> required
> * the greatest advantages to using clustered indexes, therefore, are
> cases where the physical order of the data can increase your
> performance. chief among these are (1) columns commonly used in group
> by and order by clauses (2) columns on the many side of a one-to-many
> relationship. because there is a tremendous increase to the performance
> of the reads for these operations (3) columns whose values are
> frequently evaluated between a range
> * by the same reasoning, clustered indexes are wasted on unique value
> columns, as they serve no tangible purpose (except as you mention,
> perhaps ameliorating problems using identity columns without a
> clustered index)
A row in a table with a clustered index can only be accessed through the
clustered index. There's simply no other way to find the row. If you have
a non-clustered unique index, and a non-unique clustered index then
accessing the table through the unique index will be more expensive since
you must traverse the unique index only to get, at the leaf level, a
non-unique clustered index key (plus 4-byte uniqifier), and then you must
traverse the non-unique index down to the leaf level (data page) on which
the row is located. There are situation where this is a net improvement in
performance, but for applications which do primarily single-row
insert/update/delete clustering the primary key optimizes the most important
transaction.

> * using a clustered index on a unique value is wasted. the only reason
> is the default for new tables created in enterprise manager is because
> it grants advantages to some queries above a table that has zero
> clustered indexes (better one than none)
This is not generally the case since choosing the clustered index always
optimizes some access paths and degrades others. You must analyze your
workload and measure the impace of clustering a non-unique tuple.
There are no valid sources for recieved wisdom or rules of thumb for this.
Only knoledge of how SQL Server is implemented and testing.
David|||Perhaps you should bin those books and open up BOL.
SQL Server Architecture/Database Architecture/Physical Database
Architecture/Table and Index Architecture
This section contains information about the physical structure of clustered
indexes, nonclustered indexes, and heaps (tables without clustered indexes).
Creating and Maintaining Databases/Indexes
This section contains information about when to use clustered indexes, why
you should keep the key small, etc.
"jason" <iaesun@.yahoo.com> wrote in message
news:1126206276.049357.153630@.g43g2000cwa.googlegroups.com...
> interesting, you clearly have some well informed opinions. they just
> happen to disagree with some of the sources i've used to come to my
> understanding :) these things happen. i admit, my understanding of
> clustered indexing, and indexing in general, is incomplete, but here
> are some points that i thought i'd share, to see if perhaps there's an
> absolute answer:
> * from every text at my disposal, the primary advantage to a clustered
> index is the fact that the data is guaranteed to be in the same order
> as the index.
> * the leaf nodes of a clustered index don't actually point to the next
> and previous rows, because they don't have to. the next and previous
> values are implied by the next and previous positions on disk.
> * nonclustered indexes do point to next and previous data rows, because
> the index order may not match the physical order, so a pointer is
> required
> * the greatest advantages to using clustered indexes, therefore, are
> cases where the physical order of the data can increase your
> performance. chief among these are (1) columns commonly used in group
> by and order by clauses (2) columns on the many side of a one-to-many
> relationship. because there is a tremendous increase to the performance
> of the reads for these operations (3) columns whose values are
> frequently evaluated between a range
> * by the same reasoning, clustered indexes are wasted on unique value
> columns, as they serve no tangible purpose (except as you mention,
> perhaps ameliorating problems using identity columns without a
> clustered index)
> * using a clustered index on a unique value is wasted. the only reason
> is the default for new tables created in enterprise manager is because
> it grants advantages to some queries above a table that has zero
> clustered indexes (better one than none)
> here are my sources for this information:
> microsoft sql server 2000 bible, paul nielsen, pp768-771
> sql server 2000 for experienced dba's, brian knight, pp252-255
>
http://msdn.microsoft.com/library/d...une.as
p
>
http://msdn.microsoft.com/library/d...l/sql7sapr3.asp[
color=darkred]
> these sources cite specific examples of where and why you would want to
> use clustered indexes, and they are all on data that is grouped by,
> sorted by, or evaluated in a range. especially date fields (which are
> rarely unique, yes?)
> one caveat that is mentioned is that you shouldn't apply a clustered
> index to a column that is updated often, for the reason you stated,
> that the clustered index is appended to every nonclustered index in the
> table. but you cite this as a performance hindrance? my undrestanding
> is that the presence of the clustered index is actually increasing
> performance (if at a small cost of space) by skipping the pointer to
> data page step of a lookup.
> what are your sources, that we might compare / contrast?
> jason
>[/color]|||> There are no valid sources for recieved wisdom or rules of thumb for this.
> Only knoledge of how SQL Server is implemented and testing.
I'm getting that impression, which is why discussions like these are
extremely useful. They can supplement experiences you haven't had yet,
and as you say, give a more complete picture of how SQL Server is
implemented. So thank you very much!
Jason