joining tables in view - tsql

I am now concerned that I have not normalised the tables correctly as now I see no way to join them;
I have 1 table with 2 columns called Questions, and another table called answers with 10 columns, one for the userId then 9 columns which hold all the answers (int) for each user.
Everything is working well for inserts and updates, however I am having a heck of a time trying to create a view which will show all questions, each user and each of their responses to each question.
Question table;
CREATE TABLE [dbo].[Questions](
[questionId] [int] IDENTITY(1,1) NOT NULL,
[question] [nvarchar](max) NULL,
CONSTRAINT [PK_Questions] PRIMARY KEY CLUSTERED
(
[questionId] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
Answer table;
CREATE TABLE [dbo].[Answers](
[empID] [nvarchar](10) NOT NULL,
[q1] [int] NULL,
[q2] [int] NULL,
[q3] [int] NULL,
[q4] [int] NULL,
[q5] [int] NULL,
[q6] [int] NULL,
[q7] [int] NULL,
[q8] [int] NULL,
[q9] [int] NULL,
CONSTRAINT [PK_Answers] PRIMARY KEY CLUSTERED
(
[empID] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
Nothing I have tried works, so any ideas from you all that can help me avoid re-doing the tables would be so greatly appreciated!
Thanks in advance for any help.
Alex

Seems to me that your answer table should have a foreign key to the question table. Unless an answer can refer to multiple questions, in which case I would say you should consider something like a mapping/relation table which has FKs to both answer and question tables.

I think you might need to look into pivot tables to accomplish your task.

Related

Entity Framework 7 RC1 adding nested child entities results in wrong mapping

Adding a (medium) large quantity of nested child entities through the Entity Framework 7 (Release Candidate 1) stores wrong entity->child-entity mappings.
Simplified example to reproduce the issue:
using (TestContext dbContext = new TestContext())
{
var nums = Enumerable.Range(1, 40);
var orders = nums.Select(s => new TestOrder()
{
name = s.ToString(),
TestOrderItem = nums.Take(10).Select(o => new TestOrderItem()
{
name = (s*100 + o).ToString(),
TestOrderPricing =
new[] {new TestOrderPricing() {amount = (s*100 + o), PricingType = "Principal"}}.ToList()
}).ToList()
});
dbContext.AddRange(orders);
dbContext.SaveChanges();
}
After executing that, all the relations are stored - but most of the TestPricing entities are referencing a wrong TestOrderItem-entity.
Is this an existing bug of the Entity Framework RC1 or do I have a wrong setup?
Setup for the Test-Environment:
Visual Studio 2015
DNX 4.6
EF7 RC1
1) Database first - creating the 3 tables:
CREATE TABLE [dbo].[TestOrder](
[OrderId] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](100) NULL,
CONSTRAINT [PK_Order] PRIMARY KEY CLUSTERED
(
[OrderId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[TestOrderItem](
[OrderItemId] [int] IDENTITY(1,1) NOT NULL,
[OrderId] [int] NOT NULL,
[name] [varchar](100) NULL,
CONSTRAINT [PK_OrderItem] PRIMARY KEY CLUSTERED
(
[OrderItemId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[TestOrderPricing](
[OrderItemId] [int] NOT NULL,
[PricingType] [varchar](20) NOT NULL,
[amount] [decimal](18, 2) NULL,
CONSTRAINT [PK_OrderPricing] PRIMARY KEY CLUSTERED
(
[OrderItemId] ASC,
[PricingType] 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].[TestOrderItem] WITH CHECK ADD CONSTRAINT [FK_OrderItem_Order] FOREIGN KEY([OrderId])
REFERENCES [dbo].[TestOrder] ([OrderId])
ON DELETE CASCADE
ALTER TABLE [dbo].[TestOrderItem] CHECK CONSTRAINT [FK_OrderItem_Order]
ALTER TABLE [dbo].[TestOrderPricing] WITH CHECK ADD CONSTRAINT [FK_OrderPricing_OrderItem] FOREIGN KEY([OrderItemId])
REFERENCES [dbo].[TestOrderItem] ([OrderItemId])
ON DELETE CASCADE
ALTER TABLE [dbo].[TestOrderPricing] CHECK CONSTRAINT [FK_OrderPricing_OrderItem]
2) Scaffolding the model
dnx ef dbcontext scaffold "Server=.;Database=Test;Trusted_Connection=True;" EntityFramework.MicrosoftSqlServer --outputDir Models
3) Run the example
Or download the console application with mapping included:
https://onedrive.live.com/redir?resid=352A0129BF9CBD17%2134155
Observations:
If I don't use serverside generated identity keys there is no issue
Adding entity.Property(e => e.OrderItemId).UseSqlServerIdentityColumn() (which is not added by scaffolding) does not help
Setting on each child entity the reference-property to the parent-entity does not help
With the adding of fewer entities there is no issue
Confirmed issue in RC1, verified that this is fixed in working code base and the fix will ship in RC2

Does the order in which you add records to DbSets in EF has any effect in raising Foreign Key conflicts?

In working with EF Database first, I am not being able to insert records into a specific table. I get the INSERT statement conflicted with the Foreign Key... error.
My question:
Assuming EF requires you to perform only a single dbContext.SaveChanges() at the end of your changing process, does the order you add records to the DbSets has effect on this ? Or it does not matter since the DbContext keeps track of all the changes made to the data and is itself responsible to apply them in the proper order ?
To illustrate, for 3 tables A, B and C, where B has a FK on A and C a FK on B, if I manually loop over all records I have to add to C, B and A - and do DbSet<C>.Add() before I issue DbSet<B>.Add() is problematic ?
Is it required to issue a dbContext.SaveChanges() for each table additions ?
Adding the create sql script for all 3 tables:
CREATE TABLE [dbo].[A](
[Id] [int] NOT NULL,
[a1] [int] IDENTITY(1,1) NOT NULL,
[a2] [nvarchar](50) NULL,
CONSTRAINT [PK_A] 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],
CONSTRAINT [IX_A] UNIQUE NONCLUSTERED
(
[a1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[B](
[Id] [int] IDENTITY(1,1) NOT NULL,
[a1] [int] NULL,
[b1] [int] NULL,
[b2] [nvarchar](50) NULL,
CONSTRAINT [PK_B] 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],
CONSTRAINT [IX_B] UNIQUE NONCLUSTERED
(
[b1] 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
ALTER TABLE [dbo].[B] WITH CHECK ADD CONSTRAINT [FK_B_A1] FOREIGN KEY([a1])
REFERENCES [dbo].[A] ([a1])
GO
ALTER TABLE [dbo].[B] CHECK CONSTRAINT [FK_B_A1]
GO
CREATE TABLE [dbo].[C](
[Id] [int] IDENTITY(1,1) NOT NULL,
[b1] [int] NULL,
[c1] [int] NULL,
[c2] [nvarchar](50) NULL,
CONSTRAINT [PK_C] 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
ALTER TABLE [dbo].[C] WITH CHECK ADD CONSTRAINT [FK_C_B] FOREIGN KEY([b1])
REFERENCES [dbo].[B] ([b1])
GO
ALTER TABLE [dbo].[C] CHECK CONSTRAINT [FK_C_B]
GO
I know what the error aforementioned means, but I could not find yet which data is incorrectly linked/inconsistent.
And by the way, why such errors (INSERT statement conflicted with the Foreign Key...) are not "caught" in GetValidationErrors() ?
Update:
The problem must be the way I am trying to populate the tables. But how should this be done then ?
For the scenario below:
private static void Main(string[] args)
{
//Validate_Xml_Against_Xsd.ValidateXmlAgainstXsd example = new Validate_Xml_Against_Xsd.ValidateXmlAgainstXsd();
//example.Run();
TestEntities t = new TestEntities();
A a = new A { a1 = 1000, a2 = "aaa" };
B b = new B { a1 = 1000, b1 = 87141, b2 = "bbb" };
C c = new C { b1 = 87141, c1 = 1, c2 = "ccc" };
t.C.Add(c);
t.B.Add(b);
t.A.Add(a);
//changing the order does not fix it
//t.A.Add(a);
//t.B.Add(b);
//t.C.Add(c);
int s = t.SaveChanges();
Console.WriteLine(s);
}
How should the tables be populated ? Both my DbSet.Add() attempts fail with
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_B_A1". The conflict occurred in database "Test", table "dbo.A", column 'a1'.
The statement has been terminated.
No, the order is not important. The problem here is that you seem to have foreign keys but you lack navigation properties and you never set relations between entities.
Thus, when B is persisted, it doesn't point to any valid A. A correct code should look somehow like
A a = new A() { ....
B b = new B() { a = a, ...
assuming that your navigation property from B to A is called a.

How to define a column to be both primary key and self-incremented in Transact-sql?

to define a column to be a primary key I do this
ContactID int NOT NULL PRIMARY KEY
It looks like I need still to provide the value of the ContactID when inserting rows. I want primary key to be unique and incremented (+1) as if I defined the table using the designer.
Thanks for helping
Simply do this:
ContactID int not null identity(1,1) primary key
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Contacts](
[ContactID] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Contacts] PRIMARY KEY CLUSTERED
(
[ContactID] 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
you will have to add your other columns, etc.
UPDATE: as absolute minimum statement:
CREATE TABLE Contacts(ContactID INT IDENTITY (1,1) PRIMARY KEY);

T-SQL Self Join in combination with aggregate function

I have the following table:
CREATE TABLE [dbo].[Tree](
[AutoID] [int] IDENTITY(1,1) NOT NULL,
[Category] [varchar](10) NULL,
[Condition] [varchar](10) NULL,
[Description] [varchar](50) NULL,
CONSTRAINT [PK_Tree] PRIMARY KEY CLUSTERED
(
[AutoID] 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
The data looks like this:
INSERT INTO [Test].[dbo].[Tree]
([Category]
,[Condition]
,[Description])
VALUES ('1','Alpha','Type 1')
INSERT INTO [Test].[dbo].[Tree]
([Category]
,[Condition]
,[Description])
VALUES ('1','Alpha','Type 1')
INSERT INTO [Test].[dbo].[Tree]
([Category]
,[Condition]
,[Description])
VALUES ('2','Alpha','Type 2')
INSERT INTO [Test].[dbo].[Tree]
([Category]
,[Condition]
,[Description])
VALUES ('2','Alpha','Type 2')
GO
I try now to do the following:
SELECT Category,COUNT(*) as CategoryCount FROM Tree where Condition = 'Alpha' group by Category
However, I also wish to get the Description for each Element. I tried several subqueries, self joins etc., but I always come to the problem that the subquery cannot return more than one record.
The problem is caused by a poor database design which I cannot change and I have run out of ideas as to how to get this done in a single query.
If you need description, you have to include it in the aggregate
SELECT Category ,
[Description] ,
COUNT(*) AS CategoryCount
FROM Tree
WHERE Condition = 'Alpha'
GROUP BY Category ,
[Description]

CREATE TABLE statement question in T-SQL

I am working on a pomotion database and below is what my CREATE TABLE steatment looks like:
CREATE TABLE [dbo].[sponsors]
(
[InstId] [bigint] NOT NULL,
[EncryptedData] [varbinary](44) NOT NULL,
[HashedData] [varbinary](22) NOT NULL,
[JobId] [bigint] NOT NULL,
CONSTRAINT [PK_sponsors] PRIMARY KEY CLUSTERED
(
[InstId] 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].[sponsors] WITH CHECK ADD CONSTRAINT [FK_sponsors_jobs] FOREIGN KEY([JobId])
REFERENCES [dbo].[jobs] ([Id])
GO
ALTER TABLE [dbo].[sponsors] CHECK CONSTRAINT [FK_sponsors_jobs]
GO
ALTER TABLE [dbo].[sponsors] WITH CHECK ADD CONSTRAINT [FK_sponsors_titles] FOREIGN KEY([TId])
REFERENCES [dbo].[titles] ([TId])
GO
ALTER TABLE [dbo].[sponsors] CHECK CONSTRAINT [FK_sponsors_titles]
GO
And I'd like to get rid of ALTER TABLE statements and make them part of CREATE TABLE
statements, I know how to do the most but not sure how to get CHECK CONSTRAINT during
create table, does anyone have experience with this? or know how to?
You can just add each foreign key constraint right in the CREATE TABLE declaration:
CREATE TABLE [dbo].[sponsors]
(
[InstId] [bigint] NOT NULL,
[EncryptedData] [varbinary](44) NOT NULL,
[HashedData] [varbinary](22) NOT NULL,
[JobId] [bigint] NOT NULL,
[TId] [int] NOT NULL,
CONSTRAINT [PK_sponsors] PRIMARY KEY CLUSTERED
(
[InstId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [FK_sponsors_jobs] FOREIGN KEY([JobId])
REFERENCES [dbo].[jobs] ([Id]),
CONSTRAINT [FK_sponsors_titles] FOREIGN KEY([TId])
REFERENCES [dbo].[titles] ([TId])
) ON [PRIMARY]
You seem to have missed a column (TId)
CREATE TABLE [dbo].[sponsors]
(
[InstId] [bigint] NOT NULL
CONSTRAINT [PK_sponsors] PRIMARY KEY CLUSTERED,
[EncryptedData] varbinary NOT NULL,
[HashedData] varbinary NOT NULL,
[JobId] [bigint] NOT NULL
CONSTRAINT [FK_sponsors_jobs] FOREIGN KEY REFERENCES [dbo].[jobs] ([Id]),
[TId] int NOT NULL
CONSTRAINT [FK_sponsors_titles] FOREIGN KEY REFERENCES [dbo].[titles] ([TId])
) ON [PRIMARY]
The ALTER TABLE ... CHECK CONSTRAINT command simply enables (or disables with NOCHECK) the constraint. Constraints are enabled by default when you add them, so this extra statement is redundant and not needed if you are adding the constraints in the CREATE statement.
http://msdn.microsoft.com/en-us/library/ms190273(SQL.90).aspx