I have a table in a SQL Server 2012 instance, like so
CREATE TABLE [dbo].[Test](
[SampleDateTime] [datetime] NULL,
[Unit ID] [nvarchar](4) NULL,
[WS Avg 2min] [float] NULL,
[WD Avg 2min] [float] NULL,
[WGS 10min] [float] NULL,
[WGD 10min] [float] NULL,
[Air Temp] [float] NULL,
[Rel Humidity] [float] NULL,
[Dew Point] [float] NULL,
[Pyranometer] [float] NULL,
[Quantum] [float] NULL,
[Air Pressure] [float] NULL,
[Snow Level] [float] NULL,
[Rainfall] [float] NULL,
[PW Current] [varchar](10) NULL,
[Visibility] [float] NULL,
[CBase 1] [float] NULL,
[CBase 2] [float] NULL,
[CBase 3] [float] NULL,
[Vert Vis] [float] NULL
) ON [PRIMARY]
connected to MS Access (2010) via an ODBC linked table (SQL Server Native Client 11.0)
When I open the table, I see all of the data
However, when I try a simple query
SELECT dbo_Test.* FROM dbo_Test
WHERE ( (dbo_Test.[Unit ID])="BASE") ;
I am still getting all the rows, not just the rows where [Unit ID] is "BASE"
The same query in SQL Server Mgt. Studio works just fine with only the expected results returned.
I also notice that when sorting the linked table by [Unit ID], it does not sort properly. There will be rows with data just not sorted like I would expect. (See image below, sorted Ascending by [Unit ID])
Is there a way to get this linked table to behave properly?
Your table seems to be lacking a primary key. This can cause all sorts of issues (e.g. you won't be able to write to that linked table). Although I would be surprised if the effect you see is caused by that.
But try adding an IDENTITY column as primary key, and relink the table from Access.
// Edit: too late :)
It turns out the issue was that the table did not have a primary key established. Due to our data, I could not use SampleDateTime as a primary key. So, I created a unique key on SampleDateTime + Unit ID instead
ALTER TABLE [dbo].[Test] ADD CONSTRAINT [KEY_AWAData_DateandUnitID] UNIQUE NONCLUSTERED
(
[SampleDateTime] ASC,
[Unit ID] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Now MS Access is happy to execute queries and sort as expected.
Related
I have a table in my DB which contains 5 million records:
CREATE TABLE [dbo].[PurchaseFact](
[Branch] [int] NOT NULL,
[ProdAnal] [varchar](30) NULL,
[Account] [varchar](12) NULL,
[Partno] [varchar](24) NULL,
[DteGRN] [date] NULL,
[DteAct] [date] NULL,
[DteExpect] [date] NULL,
[OrderNo] [bigint] NULL,
[GRNNO] [varchar](75) NULL,
[SuppAdv] [varchar](75) NULL,
[Supplier] [varchar](12) NULL,
[OrdType] [varchar](4) NULL,
[UnitStock] [varchar](4) NULL,
[OrderQty] [float] NULL,
[RecdQty] [float] NULL,
[Batch] [varchar](100) NULL,
[CostPr] [float] NULL,
[Reason] [varchar](2) NULL,
[TotalCost] [float] NULL,
[Magic] [bigint] IDENTITY(1,1) NOT NULL,
PRIMARY KEY CLUSTERED
(
[Magic] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
As you can see from the above - a CLUSTERED INDEX is being used on the MAGIC column which is a UNIQUE column.
Data retrieval time for the following SELECT statement is well over 8mins which causes reporting issues:
SELECT Branch,
Supplier,
ProdAnal,
DteGRN AS Date,
PartNo AS Partno,
OrderNo,
OrderQty,
TotalCost,
CostPr
FROM dbo.PurchaseFact src
WHERE YEAR(DteGRN) = 2016
Excluding the WHERE clause also doesn't make the query run any faster.
I have tried, together with the CLUSTERED index to include a UNIQUE index in the hopes that it would run faster but to no avail :
CREATE UNIQUE INDEX Unique_Index ON dbo.PurchaseFact ([Branch], [Supplier], [Magic])
INCLUDE ([ProdAnal], [Account], [Partno], [DteAct], [DteExpect], [OrderNo], [GRNNO],
[SuppAdv], [OrdType], [UnitStock])
Is there any way I can optimize performance time on this table or should I resort to archiving old data?
Any advice would be greatly appreciated.
This is your where clause:
WHERE YEAR(DteGRN) = 2016
If the table has 5 million rows, then this is going to return a lot of data, assuming any reasonable distribution of dates. The volume of data is probably responsible for the length of time for the query.
One thing you can do is to rephrase the WHERE and then put an index on the appropriate column:
WHERE DteGRN >= '2016-01-01' and DteGRN < '2017-01-01'
This can then take advantage of an index on PurchaseFact(DteGRN). However, given the likely number of rows being returned, the index probably will not help very much.
The bigger question is why your reporting application is bringing back all the rows from 2016, rather than summarizing them inside the database. I suspect you have an architecture issue with the reporting application.
Sorry, can't add comments.
To help improve performance further (if you can live with the UPDATE overhead), create a COVERING INDEX that INCLUDES only the columns in the SELECT part of the query.
I have a design/performance question.
I have this next table.
CREATE TABLE [dbo].[DW_Visits_2016](
[VisitId] [int] NOT NULL,
[UserId] [int] NOT NULL,
[VisitReferrer] [varchar](512) NULL,
[VisitFirstRequest] [varchar](255) NOT NULL,
[VisitAppName] [varchar](255) NULL,
[VisitCountry] [varchar](50) NULL,
[VisitDate] [smalldatetime] NOT NULL,
[VisitMins] [int] NOT NULL,
[VisitHits] [int] NOT NULL,
[EntryTag] [varchar](100) NOT NULL,
[VisitCount] [int] NOT NULL,
[VisitInitialDate] [datetime] NOT NULL,
[AggregateType] [varchar](50) NULL,
[MemberId] [int] NULL,
[ServerName] [varchar](50) NULL,
[BrowserUserAgent] [varchar](255) NULL,
[LastModifiedDate] [smalldatetime] NULL,
[Guid] [uniqueidentifier] NULL,
[SessionId] [varchar](100) NULL,
[IPAddress] [varchar](40) NULL,
CONSTRAINT [PK_Visits] PRIMARY KEY NONCLUSTERED
(
[VisitId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Visits] WITH CHECK ADD CONSTRAINT [CK_Visits_VisitDate] CHECK (([VisitDate]>='2016-01-01' AND [VisitDate]<'2017-01-01'))
GO
ALTER TABLE [dbo].[Visits] CHECK CONSTRAINT [CK_Visits_VisitDate]
And this same table for 2015 ... 2010.
Every table has around 150 million rows. So, combined we are talking about 1,050 million rows.
I received a requirement where BI people wants to have this combined on a single view (Something crazy like select * from all_visits).
Luckily they gave me some ‘where’ clauses, and some columns they don’t need, so the final result would be 6 columns and 20% of the rows (210 million rows), but nonetheless, a ‘view’ is just a stored query. Even though the box has 60GB of ram, it’s shared with many other databases.
Options I see:
Instead of a view… Creating the views as tables and move them to a dedicated box.
Create one view per year?
Switch all of this to mongodb or something like vertica?!
Any of the previous options combined with column stored indexes?
All examples of table partitioning that I have found are quite simple but I need to partition many tables by one criteria.
For example I have tables: Contractors and Products where ContractorId in Products table is a foreign key.
I created function and schema for ContractorId. It works perfectly for Contractors table but when it comes to the Products table...
I have no idea how should I use it because when I try I always got the information: "The filegroup 'PRIMARY' specified for the clustered index 'PK_dbo.Products' was used for table 'dbo.Products' even though partition scheme 'scheme_Contractors' is specified for it". My Products table looks like:
CREATE TABLE [dbo].[Products](
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[Amount] [int] NULL,
[Color] [nvarchar](max) NULL,
[Price] [decimal](18, 2) NULL,
[Guarantee] [nvarchar](max) NULL,
[GuaranteeType] [int] NULL,
[AdditionalFeatures] [nvarchar](max) NULL,
[Valid] [bit] NULL,
[ContractorId] [int] NOT NULL,
[ProducerId] [int] NOT NULL,
[ProductCategoryId] [int] NOT NULL,
CONSTRAINT [PK_dbo.Products] PRIMARY KEY ( [ProductId] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] )
GO
ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_dbo.Products_dbo.Contractors_ContractorId] FOREIGN KEY([ContractorId])
REFERENCES [dbo].[Contractors] ([ContractorId])
GO
ALTER TABLE [dbo].[Products] CHECK CONSTRAINT [FK_dbo.Products_dbo.Contractors_ContractorId]
GO
Could anymone tell me please - is it possible to use my schema on ContractorId column and how? Thank you in advance!
In agreement with Dan Guzman, I'd like to point out there should be no [PRIMARY] specification in the table definition.
We use partitioning on large scale. It is very comfortable to partition all tables on the same partitioning scheme, because the SQL engine will use its multi-processor paralellisation capabilities to the full.
When a certain group of partitions is in one database file and another paration in another file you can even become flexible with disc-usage and backups.
So you first need a partition function to define the values of the partitioning scheme:
CREATE PARTITION FUNCTION [ContractorPartitionFunction](int) AS RANGE LEFT
FOR VALUES (contractor1,contractor2,...)
Then you need to create the partition scheme
CREATE PARTITION SCHEME [ContractorPartitionScheme]
AS PARTITION [ContractorPartitionFunction]
TO ([File_001],[File_002],...,[PRIMARY])
Then for all tables and indexes you now create you should remove ON [PRIMARY] from the definitions as the target filegroup, but instead you should use
ON [ContractorPartitionScheme](ContractorId)
So you table definition should now read:
CREATE TABLE [dbo].[Products](
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[Amount] [int] NULL,
[Color] [nvarchar](max) NULL,
[Price] [decimal](18, 2) NULL,
[Guarantee] [nvarchar](max) NULL,
[GuaranteeType] [int] NULL,
[AdditionalFeatures] [nvarchar](max) NULL,
[Valid] [bit] NULL,
[ContractorId] [int] NOT NULL,
[ProducerId] [int] NOT NULL,
[ProductCategoryId] [int] NOT NULL)
ON ContractorPartitionScheme(ContractorId)
CREATE UNIQUE NONCLUSTERED INDEX PK_dbo.Products ON Products
(
productId,
ConstructorId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON ContractorPartitionScheme(ContractorId)
I am currently trying to execute some SQL Query in SQLSERVER 2008 R2 form my Java GUI. I am working on currency management system.
I have to store Long data type values as the figure of currency may exceed than 10 digits but the computed column dose not show any data type option in the design view of the table. I really Need help regarding this as my value exceeds than 10 digits and I need to select total value from my database. I have tried to execute the code but its showing some sort of overflow error please help
The following is my script file of the table from database name CNV
USE [CNV]
CREATE TABLE [dbo].[soil_det](
[ID] [int] IDENTITY(1,1) NOT NULL,
[rm_id] [bigint] NULL,
[box_no] [int] NULL,
[weight] [decimal](18, 2) NULL,
[note_state] [varchar](10) NULL,
[dm_state] [varchar](10) NULL,
[1] [int] NULL,
[2] [int] NULL,
[5] [int] NULL,
[10] [int] NULL,
[20] [int] NULL,
[50] [int] NULL,
[100] [int] NULL,
[500] [int] NULL,
[1000] [int] NULL,
[tp] AS (((((((([1]+[2])+[5])+[10])+[20])+[50])+[100])+[500])+[1000]),
[tv] AS (((((((([1]*(1)+[2]*(2))+[5]*(5))+[10]*(10))+[20]*(20))+[50]*(50))+[100]*(100))+[500]*(500))+[1000]*(1000)) PERSISTED,
[tp_ex1] AS ((((((([2]+[5])+[10])+[20])+[50])+[100])+[500])+[1000]),
[tv_ex1] AS ((((((([2]*(2)+[5]*(5))+[10]*(10))+[20]*(20))+[50]*(50))+[100]*(100))+[500]*(500))+[1000]*(1000)),
[val_1] AS ([1]*(1)),
CONSTRAINT [PK_mut_det] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
here is solution for this , you can do something as given in image
Check the full article over here : SQL SERVER – Puzzle – Solution – Computed Columns Datatype Explanation
I am newbiew using VBA/FK/SQL server all in one. I am creating simple purchase order workbook user interface in excel.
I have created two tables:
CREATE TABLE [dbo].[PurchaseOrder](
[PKPurchaseOrderID] [bigint] IDENTITY(1,1) NOT NULL,
[PurchaseOrderNumber] [bigint] NULL,
[PurchaseOrderDate] [date] NULL,
[PurchaseOrderTime] [int] NULL,
[PurchaseOrderSupplierID] [nvarchar](50) NULL,
[ShipToA1] [nvarchar](50) NULL,
[ShipToA2] [nvarchar](50) NULL,
[ShipToA3] [nvarchar](50) NULL,
[ShipToA4] [nvarchar](50) NULL,
CONSTRAINT [PK_PurchaseOrder] PRIMARY KEY CLUSTERED
(
[PKPurchaseOrderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
and
CREATE TABLE [dbo].[PurchaseOrderLines](
[PKPurchaseOrderLineID] [bigint] IDENTITY(1,1) NOT NULL,
[FKPurchaseOrderID] [bigint] NULL,
[Quantity] [smallint] NULL,
[Item] [nchar](25) NULL,
[Description] [nvarchar](50) NULL,
[siteID] [nchar](10) NULL,
[UnitPrice] [money] NULL,
[LineTotal] [money] NULL,
CONSTRAINT [PK_PurchaseOrderLines] PRIMARY KEY CLUSTERED
(
[PKPurchaseOrderLineID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[PurchaseOrderLines] WITH CHECK ADD CONSTRAINT
[FK_PurchaseOrderLines_PurchaseOrder] FOREIGN KEY([FKPurchaseOrderID])
REFERENCES [dbo].[PurchaseOrder] ([PKPurchaseOrderID])
ALTER TABLE [dbo].[PurchaseOrderLines] CHECK CONSTRAINT
[FK_PurchaseOrderLines_PurchaseOrder]
GO
I want to achieve that in the background when user clicks the button both tables are updated.
I am not sure how I can link brand new row created in the PurchaseOrder table with FK in the PurchaseorderLine table.
What i plan to do for single user interface:
Insert New Order
Use Max(PKPurchaseOrderID) as FK for new order lines table.
How can I determine currently inserted Order ID(PKPurchaseOrderID) if multiple users are working/submitting orders at the same time. I am afraid order lines may be assigned to different orders if I use my plan. e.g.
Please advise.
I use SQL Server 2008 and Excel 2007/2010
Many thanks
I would create a stored procedure that inserts the new row and returns the ID with SCOPE_IDENTITY()
Here's a decent article on the different "identity" methods in SQL Server.
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/