How to Insert into 2 Tables ProductOrder and ProductOrderLine using VBA & Foreign Keys in Excel - sql

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/

Related

Is it a good practice to apply multiple foreign key id on the same column

I have a table where I am storing different documents of different source as follows
CREATE TABLE [dbo].[Document](
[DocumentId] [int] IDENTITY(1,1) NOT NULL,
[EntityId] [int] NOT NULL,
[DocumentGuid] [uniqueidentifier] NOT NULL,
[DocumentTypeCdId] [int] NOT NULL,
[DocumentName] [nvarchar](500) NOT NULL,
[DocumentType] [nvarchar](500) NOT NULL,
[DocumentData] [nvarchar](max) NOT NULL,
[IsSuppressed] [bit] NULL,
[CreatedBy] [nvarchar](200) NULL,
[CreatedDt] [datetime] NULL,
[UpdatedBy] [nvarchar](200) NULL,
[UpdatedDt] [datetime] NULL,
CONSTRAINT [PK_Document] PRIMARY KEY CLUSTERED
(
[DocumentId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[Document] WITH CHECK ADD CONSTRAINT [FK_Document_DocumentTypeCd] FOREIGN KEY([DocumentTypeCdId])
REFERENCES [dbo].[DocumentTypeCd] ([DocumentTypeCdId])
GO
ALTER TABLE [dbo].[Document] CHECK CONSTRAINT [FK_Document_DocumentTypeCd]
GO
EntityId will be from different source tables, so can I add this column to be a FK of all those source table. Currently I have nearly 10 Source tables. If not what is the better approach to handle this scenario
You have a problem in the design of your database. In such a case you need to have a parent ancestor table that hold the keys of all type of documents, then multiple children table, each one speciallized for a speciic document type.
This is called inheritance and children must not share the same key value (children table with excusion ids...)

Clustered Index Update Slow Update On Large Table

I am having a problem updating a large table with millions of rows please advice to reduce the update time.
Table definition
CREATE TABLE [dbo].[tbl_sms_job_detail](
[JobDetailID] [int] IDENTITY(1,1) NOT NULL,
[JobID] [int] NULL,
[DistributorID] [int] NULL,
[ResellerID] [int] NULL,
[CustomerID] [int] NULL,
[SenderID] [nvarchar](50) NULL,
[PhoneNumber] [nvarchar](100) NULL,
[SMSMessage] [nvarchar](1000) NULL,
[MessageType] [nvarchar](50) NULL,
[MessageLength] [int] NULL,
[MessageParts] [int] NULL,
[ClientRate] [decimal](18, 5) NULL,
[ClientCost] [decimal](18, 5) NULL,
[ResellerRate] [decimal](18, 5) NULL,
[ResellerCost] [decimal](18, 5) NULL,
[DistributorRate] [decimal](18, 5) NULL,
[DistributorCost] [decimal](18, 5) NULL,
[RouteDetailID] [int] NULL,
[SMSID] [nvarchar](200) NULL,
[DLRStatus] [nvarchar](100) NULL,
[ErrorCode] [int] NULL,
[ErrorDescription] [nvarchar](2000) NULL,
[SentDate] [datetime] NULL,
[SentDateUTC] [datetime] NULL,
[SMSSource] [nvarchar](50) NULL,
[SMSType] [nvarchar](100) NULL,
[APISMSID] [int] NULL,
[DLRDate] [datetime] NULL,
[DLRDateUTC] [datetime] NULL,
CONSTRAINT [PK_tbl_sms_job_detail] PRIMARY KEY CLUSTERED
(
[JobDetailID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20170919-173756] ON [dbo].[tbl_sms_job_detail] ( [JobID] ASC, [DLRStatus] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20170919-174142] ON [dbo].[tbl_sms_job_detail]
(
[SMSID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
Update Procedure
CREATE Procedure [dbo].[sp_update_message_status]
#SMSID nvarchar(200),
#DLRStatus nvarchar(100),
#ErrorCode int,
#ErrorDescription nvarchar(2000)
AS
UPDATE tbl_sms_job_detail SET DLRStatus = #DLRStatus, ErrorCode = #ErrorCode, ErrorDescription = #ErrorDescription WHERE SMSID = #SMSID
Execution Plan
This Procedure is called up to 1000 times in several minutes and some of them fail to update as it takes time to update the previous record what can be done to increase the update of a record in this table.
I suspect that the issue is not being caused by the actual clustered index but by the effect the update query has.
MSSQL is a page based storage system. When adding records to the table, as the clustered index is on the field [JobDetailID] [int] IDENTITY(1,1) NOT NULL, each new record is applied to the last page currently at the table (if it will fit) or a new page is tacked onto the end of the table and the record stored in it.
Assuming that [DLRStatus] and/or [ErrorDescription] start of a null or empty strings, when the update sproc runs, it has to find some space in the page that the record is already in to store the new value in. SQL keeps a little space in each page file for such purpose, but when that space is used up, it will have to do a page split - splitting the contents of the one page file into the existing page file and a newly created blank page file. As the primary key is clustered, this new page file has to be inserted so it keeps the records stored in the table in the clustered index order. It is quite likely that this page splitting is at the root of the problem.
The amount of space that SQL keeps back before creating a new page is configurable, therefore one solution is to initially create the page files with plenty of 'expansion' room. On an index it is called the fill factor, but I am not sure what the correct term is for data pages (probably still a fill factor, but not sure).
Another alternative is to store the returned error information in a separate table and then store the primary key for the 'error information' record in table [tbl_sms_job_detail]. As long as the key is not a nvarchar / varchar (and who would do this anyway), the space required in the page file will already be reserved. Thus recording the error information requires appending the variable text information to the end of the last page file for the new table and updating a foreign key in your original table that already has space reserved for it and so doesn't trigger of a page slit.

Attempted to read or write protected memory - .NET EF + Web API

I have a relatively simple application that pulls SQL data via a .NET Web API using EF6. There are three tables in the database:
Product
CREATE TABLE [dbo].[Product]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
[FullName] [varchar](max) NOT NULL,
[Description] [varchar](max) NOT NULL,
[BranchID] [int] NOT NULL,
[ProgramID] [int] NOT NULL,
[TechnologyPlatformID] [int] NOT NULL,
[StatusID] [int] NOT NULL,
[FunctionID] [int] NOT NULL,
[ProgramManagerID] [int] NOT NULL,
[TypeID] [int] NOT NULL,
[Vendor] [varchar](max) NOT NULL,
[VendorPOC] [varchar](max) NOT NULL,
[URL] [varchar](255) NULL,
[Code] [varchar](50) NULL,
[CreatedBy] [int] NOT NULL,
[CreateDate] [datetime] NOT NULL,
[ModifiedBy] [int] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Product]
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] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Product] WITH CHECK
ADD CONSTRAINT [FK_Product_Function]
FOREIGN KEY([FunctionID]) REFERENCES [dbo].[Function] ([ID])
GO
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_Product_Function]
GO
ALTER TABLE [dbo].[Product] WITH CHECK
ADD CONSTRAINT [FK_Product_Program]
FOREIGN KEY([ProgramID]) REFERENCES [dbo].[Program] ([ID])
GO
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_Product_Program]
GO
Program:
CREATE TABLE [dbo].[Program]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
CONSTRAINT [PK_Program]
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]
GO
SET ANSI_PADDING OFF
GO
Function:
CREATE TABLE [dbo].[Function]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
[Description] [varchar](max) NOT NULL,
CONSTRAINT [PK_Function_1]
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] TEXTIMAGE_ON [PRIMARY]
GO
My EDMX looks normal:
And here's how I'm accessing the data in my repo:
Suddenly I'm getting the following error when calling GetProducts():
An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I can't seem to figure out what's causing this. Here's what I have tried:
Made sure "Suppress JIT optimization..." was unchecked in VS
Repaired .NET Framework on my local machine
Neither worked...however, if I delete the Function table in SQL and update my EDMX, the issue is resolved. Why would this table be causing the issue?
Appreciate any input, thank you!
Try turning proxy generation off, and see if you still get the same problem.
My initial guess would be that you are including the Program directly via .Include(x => x.Program), but Function navigation property is being proxied into a lazy property. And when WebAPI tries to serialize it, it throws an error.

Table partitioning on sql server by foreign key column

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)

enforce primary key to exist in another multi colum primary key

I have two tables. First table has multi columns as the primary key and the second table has one column primary key. Data has be entered first in Table1 FieldPlacement where FieldPlacementNum will be generated then enter a record in Table2 where the FieldPlacementNum has to exist in Table1.
Currently has one to many relationship but I want the reverse the relationship of tables and SQL does not let me do it. thanks
Table 1
CREATE TABLE [dbo].[FieldPlacement]
(
[ID] [varchar](10) NOT NULL,
[Year] [varchar](10) NOT NULL,
[Term] [varchar](10) NOT NULL,
[PlacementNum] [int] IDENTITY(1,1) NOT NULL,
[Email] [varchar](70) NULL,
CONSTRAINT [PK_FieldPlacement]
PRIMARY KEY CLUSTERED ([ID] ASC, [Year] ASC, [Term] ASC, [PlacementNum] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[FieldPlacement] WITH CHECK
ADD CONSTRAINT [FK_FieldPlacement_FieldPlacementEval1]
FOREIGN KEY([PlacementNum])
REFERENCES [dbo].[FieldPlacementEval] ([PlacementNum])
GO
ALTER TABLE [dbo].[FieldPlacement]
CHECK CONSTRAINT [FK_FieldPlacement_FieldPlacementEval1]
GO
Table 2
CREATE TABLE [dbo].[FieldPlacementEval]
(
[PlacementNum] [int] NOT NULL,
[StudentLastName] [varchar](50) NULL,
[StudentFirstName] [varchar](50) NULL,
[TeacherLastName] [varchar](50) NULL,
[TeacherFirstName] [varchar](50) NULL,
CONSTRAINT [PK_FieldPlacementEval]
PRIMARY KEY CLUSTERED ([PlacementNum] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Since FieldPlacement.PlacementNum is an IDENTITY, which is NOT NULL and unique, you could also make this your PK, and then just create a unique index on those four columns that currently make up the PK (to ensure their uniqueness).
From your FieldPlacementEval just reference the PlacementNum.
The additional benefit here would be a smaller, more efficient clustering key on your FieldPlacement table (since it's only 1 column instead of 4 - and skips all those variable length columns which are really bad for a clustering key)