I'm developing a program in Visual studio, it's a fairly simple menu system for a hypothetical restauraunt and essentially provides the users with a series of forms with questions, and eventually gives them options, they can then build up a list of meal items etc. and get given cost and similar.
Information on the products is stored in an SQL database , such as the name, price, calories etc.
I've had a look around however I'm struggling to, if it's even possible find a way of referencing a specific field or row within the database, either by a name or a Key.
Is this possible?
Regards.
I think all you are asking about is a Primary Key?
Example Table
Product
------------
ProductId|Name |Cost|
1 |Apple |1.50|
2 |Orange|2.00|
Example Query To Pull Only the Apple
SELECT Name, Cost
FROM Product
WHERE ProductId = 1
How to create a table that will automatically generate these unique keys in SQL Server
CREATE TABLE Product (ProductId INT IDENTITY(1,1), Name VARCHAR(50),
Cost FLOAT(2))
How data would be inserted to utilize the auto key generation. Followed with a way to get the new identity
INSERT INTO Product (Name, Cost) VALUES ('Apple', 1.50)
RETURN ##IDENTITY
Hopefully that gives you a push in the right direction?
Related
I have been working on a SQL Server project that allows the users of a shopping website to insert their reviews for the product they bought.
Basically, I have 4 tables:
Customer: (Customer_ID, Username, Telephone_number, Grade)
Product: (Product_ID, Product_code, Name)
Review: (Review ID, Title, Content, Product_ID, Customer_ID)
Bill: (Bill_ID, Date, Product_ID, Customer_ID)
I've got two problems:
Firstly, I don't know how to force that only people who bought a product can review it.
Secondly, I don't know how to increase the grade in Customer table by a certain number of points (bonus points) after they review of a product.
Can anyone tell me how to solve these problems, especially in SQL Server code?
Several ways that you can do to protect your Review table from inserting such these records and it is best to handle these in your server-side or client-side code but as a design point of your DB, I think the best is to:
Design your Review table like:
(Review_ID, Title, Content, Bill_ID)
and set you Bill_Id column to not allow NULL, so that every review record must relate to a bill (shopping) record then you can handle error in your code which warns the users or...
Also if your grade is only about reviewing, you can set bonus (grade) a ratio of reviews so the grade would be like:
SELECT 5*COUNT(*) -- for example two reviews = 10 bonus
FROM Review
GROUP BY Customer_ID
And one more time I suggest you to handle all these in your code not in your DB.
Another suggestion is (If the logic and business of your application is based on database - which a shopping website is not!!) - is to create a stored procedure for INSERT operation like usp_ReviewInsert and call it in your code as a user wants to post a review, then your stored procedure handles all validating stuff (like relation between Bill and Review) and all updating stuff (like updating grade to a higher) and the insert operation in itself.
Not sure if this is the right way to phrase the question but I have a database shown below
ProductA ProgramA
ProductB ProgramB
ProductC ProgramBoth
One issue I'm facing is when I put this into a dashboard and I use the dashboard to filter only ProgramA, I want to see both Product A and Product C. And when I filter ProgramB, I would like to see both Product B and Product C. Technically the user can select two of the programs in the dashboard drop down ("ProgramA + ProgramBoth), but they don't.
Am I pushing the limits of SQL? Is there a way around? As a note, I'm importing this from a Google Sheet, so I can change the underlying values if that's easier. In Google Sheets, I have a dropdown so only one value can be put in at a time (can be changed).
You are not pushing the limits of SQL :-)
What you are describing is a many-to-many relationship, and instead of thinking about a relationship of "both", think about it as a row for each relationship so for product C you will have 2 rows - one for program A and one for program B, something along the lines of:
CREATE TABLE Product_Programs
(
Product VARCHAR(10) NOT NULL REFERENCES Products(Product),
Program VARCHAR(10) NOT NULL REFERENCES Programs(Program),
PRIMARY KEY (Product, Program)
);
INSERT INTO Product_Programs (Product, Program)
VALUES ('ProductA', 'ProgramA'),
('ProductB', 'ProgramB'),
('ProductC', 'ProgramA'),
('ProductC', 'ProgramB');
Now you can easily query for any product participating in a program with
SELECT Product
FROM Product_Programs
WHERE Program = 'ProgramA';
Which will return both product A and product C.
HTH
I want to stack items in users their inventory.
If you have a new weapon with the same ItemID, it just creates a new row like in the picture below.
If the ItemID exists then it needs to change the quantity to the number of weapons you've actually got, and delete the duplicate rows.
What type of query is that, or help me on the way?
There are various problems in your table design. First, I do not understand the purpose of InventoryID here. Because the InventoryID is unique (which I would assume to be the primary key, that's why every time when you have an additional itemID (same or not), it will be treated as a new row.
I do not know what you're trying to achieve in the end, but,
Option 1: Create a separate table Inventory with InventoryID and probably ItemID and LeasedUntil, then modify your current table to only CustomerID and ItemID and quantity
Option 2: keep your current table, add another table called Item that has only ItemID and Quantity
You may also want to review table Normalization here: http://support.microsoft.com/kb/283878
Your current table is in 1NF
If I were to have an online shopping website that sold apples and monitors and these were stored in different tables because the distinguishing property of apples is colour and that of monitors is resolution how would I add these both to an invoice table whilst still retaining referential integrity and not unioning these tables?
Invoices(InvoiceId)
|
InvoiceItems(ItemId, ProductId)
|
Products(ProductId)
| |
Apples(AppleId, ProductId, Colour) Monitors(MonitorId, ProductId, Resolution)
In the first place, I would store them in a single Products table, not in two different tables.
In the second place, (unless each invoice was for only one product) I would not add them to a single invoice table - instead, I would set up an Invoice_Products table, to link between the tables.
I suggest you look into Database Normalisation.
A question for your data model is You need a reference scheme will you use to identify products? Maybe SKU ?
Then identify each apple as a product by assigning an SKU. Likewise for monitors. Then use the SKU in the invoice item. Something like this:
product {sku}
key {sku};
invoice_item {invoice_id, sku}
key {invoice_id, sku} ;
apple {color, sku}
key {color}
key {sku};
monitor {size, sku}
key {size}
key {sku};
with appropriate constrains... in particular, the union of apple {sku} and monitor {sku} == product {sku}.
So Invoice table has a ProductID FK, and a ProductID can be either an AppleID (PK color) or MonitorID (PK resolution)?
If so, you can introduce a ProductTypeID with values like 0=apple, 1=monitor, or a isProductTypeApple boolean if there's only ever going to be 2 product types, and include that in the ProductID table PK.
You also need to include the ProductTypeID field in the Apple table and Monitor table PK.
I like name-value tables for these...It might be easier to redesign so it goes 'Product' and then 'product details'...product details holds the product id, the detail type and then the value. This would allow you to hold apples and monitors in the same table regardless of identifying attribute (and leave it open for other product to be added later on).
Similiar approach can be taken in the invoice table...have a 'product_type' column that tells you which table to look into (apple or monitor) and then a 'product_id' that references whatever ID column is in the apple/monitor table. Querying on a setup like this is a bit difficult and may force you to use dynamic sql...I'd only take this route if you have no control over doing the redesign above (and other answers posted here refer to)
First solution is preferential I would think...change the design on this db to the name value pair with the products and you'll save headaches writing your queries later.
In our application user can create different lists (like sharepoint) for example a user can create a list of cars (name, model, brand) and a list of students (name, dob, address, nationality), e.t.c.
Our application should be able to query on different columns of the list so we can't just serialize each row and save it in one row.
Should I create a new table at runtime for each newly created list? If this was the best solution then probably Microsoft SharePoint would have done it as well I suppose?
Should I use the following schema
Lists (Id, Name)
ListColumns (Id, ListId, Name)
ListRows (Id, ListId)
ListData(RowId, ColumnId, Value)
Though a single row will create as many rows in list data table as there are columns in the list, this just doesn't feel right.
Have you dealt with this situation? How did you handle it in database?
what you did is called EAV (Entity-Attribute-Value Model).
For a list with 3 columns and 1000 entries:
1 record in Lists
3 records in ListColumns
and 3000 Entries in ListData
This is fine. I'm not a fan of creating tables on-the-fly because it could mess up your database and you would have to "generate" your SQL queries dynamically. I would get a strange feeling when users could CREATE/DROP/ALTER Tables in my database!
Another nice feature of the EAV model is that you could merge two lists easily without droping and altering a table.
Edit:
I think you need another table called ListRows that tells you which ListData records belong together in a row!
Well I've experienced something like this before - I don't want to share the actual table schema so lets do some thought exercises using some of the suggested table structures:
Lets have a lists table containing a list of all my lists
Lets also have a columns table containing the metadata (column names)
Now we need a values table which contains the column values
We also need a rows table which contains a list of all the rows, otherwise it gets very difficult to work out how many rows there actually are
To keep things simple lets just make everything a string (VARCAHR) and have a go at coming up with some queries:
Counting all the rows in a table
SELECT COUNT(*) FROM [rows]
JOIN [lists]
ON [rows].list_id = [Lists].id
WHERE [Lists].name = 'Cars'
Hmm, not too bad, compared to:
SELECT * FROM [Cars]
Inserting a row into a table
BEGIN TRANSACTION
DECLARE #row_id INT
DECLARE #list_id INT
SELECT #list_id = id FROM [lists] WHERE name = 'Cars'
INSERT INTO [rows] (list_id) VALUES (#list_id)
SELECT #row_id = ##IDENTITY
DECLARE #column_id INT
-- === Need one of these for each column ===
SELECT #column_id = id FROM [columns]
WHERE name = 'Make'
AND list_id = #list_id
INSERT INTO [values] (column_id, row_id, value)
VALUES (#column_id, #row_id, 'Rover')
-- === Need one of these for each column ===
SELECT #column_id = id FROM [columns]
WHERE name = 'Model'
AND list_id = #list_id
INSERT INTO [values] (column_id, row_id, value)
VALUES (#column_id, #row_id, 'Metro')
COMMIT TRANSACTION
Um, starting to get a little bit hairy compared to:
INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro')
Simple queries
I'm now getting bored of constructing tediously complex SQL statements so maybe you can have a go at coming up with equivalent queries for the followng statements:
SELECT [Model] FROM [Cars] WHRE [Make] = 'Rover'
SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
WHERE [Owners].Age > 50
SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
JOIN [Addresses] ON [Addresses].id = [Owners].address_id
WHERE [Addresses].City = 'London'
I hope you are beginning to get the idea...
In short - I've experienced this before and I can assure you that creating a database inside a database in this way is definitely a Bad Thing.
If you need to do anything but the most basic querying on these lists (and literally I mean "Can I have all the items in this list please?"), you should try and find an alternative.
As long as each user pretty much has their own database I'll definitely recommend the CREATE TABLE approach. Even if they don't I'd still recommend that you at least consider it.
Perhaps a potential solution would be the creating of lists can involve CREATE TABLE statements for those entities/lists?
It sounds like the db structure or schema can change at runtime, or at the user's command, so perhaps something like this might help?
User wants to create a new list of an entity never seen before. Call it Computer.
User defines the attributes (screensize, CpuSpeed, AmountRAM, NumberOfCores)
System allows user to create in the UI
system generally lets them all be strings, unless can tell when all supplied values are indeed dates or numbers.
build the CREATE scripts, execute them against the DB.
insert the data that the user defined into that new table.
Properly coded, we're working with the requirements given: let users create new entities. There was no mention of scale here. Of course, this requires all input to be sanitized, queries parameterized, actions logged, etc.
The negative comment below doesn't actually give any good reasons, but creates a bit of FUD. I'd be interested in addressing any concerns with this potential solution. We haven't heard about scale, security, performance, or usage (internal LAN vs. internet).
You should absolutely not dynamically create tables when your users create lists. That isn't how databases are meant to work.
Your schema is correct, and the pluralization is, in my opinion, also correct, though I would remove the camel case and call them lists, list_columns, list_rows and list_data.
I would further improve upon your schema by skipping rows and columns tables, they serve no purpose. Simply have a row/column number attached to each cell, and keep things sparse: Don't bother holding empty cells in the database. You retain the ability to query/sort based on row/column, your queries will be (potentially very much) faster because the number of list_cells will be reduced, and you won't have to do any crazy joining to link your data back to its table.
Here is the complete schema:
create table lists (
id int primary key,
name varchar(25) not null
);
create table list_cells (
id int primary key,
list_id int not null references lists(id)
on delete cascade on update cascade,
row int not null,
col int not null,
data varchar(25) not null
);
It sounds like you might have Sharepoint already deployed in your environment.
Consider integrating your application with Sharepoint, and have it be your datastore. No need to recreate all the things you like about Sharepoint, when you could leverage it.
It'd take a bit of configuring, but you could call SP web services to CRUD your list data for you.
inserting list data into Sharepoint via web services
reading SP lists via web services
Sharepoint 2010 can also expose lists via OData, which would be simple to consume from any application.