Updating Checked ListBox values in Database - c#

Lets say I have a DataBase table that associates an Id with multiple items.
Say ID with favorite food.
So it looks like
Id FoodId
----------
1 1
1 54
1 543
2 42
2 4234
etc
I can select/ unselect favorite food values using my checked list box
When I update the db after I edit the items, do I go back and delete all previous entries in the table with Id 1 and then enter the whole new set or is there a better way of doing this?

The easiest way would be your approach. But it is also the slowest and generates redundant database operations. The correct way would be to have the old and the new list in memory creating delete, insert statements accordingly.
Compare the two lists and remove all identical values from both lists.
Create DELETEstatements for all remaining values in the 'old' list.
Create INSERTstatements for all remaining values in the 'new' list.

DELETE
FROM favfood
WHERE id=#Id and foodid not in(new_list_of_food_ids)
// serialized new_list_of_food_ids
INSERT INTO favfood(id,foodid)
(SELECT #Id, [int]
FROM OPENXML (#idoc, '/ArrayOfInt/int',1)
WITH ([int] int '.')
where [int] not in (select foodid from favfood where id=#Id))

Related

How to insert deleted rows in another table in sql

I have two tables in my sample database. These are called:
Active Products.
Inactive Products
In my asp form I have two list boxes and a dropdown list.
DropDown List: Category.
When I select any one category like milk products in my dropdown list, it will show these products under list in the category on my Left side.
Products to Active. - [ Left Side ]
Activated Products. - [ Right side ]
I used to buttons for move the list items for move left and right side. When I click an update button, it will take the list items what contains on right side list box and insert these items in first table called Active Products.
Now I select two list items on my right side and I move them to left side list box and click update button, that moved items are updated in second table. How do I do this?
Active table:
Categoryid | Produtid
-----------+-----------
1 1
1 5
1 6
Example if i select a first category, that corresponding products were display in right side, if i move Productid 5 and 6 on left side.
It will be deleted in this table updated on in-active table.
My expected output will be look like this, how to wrote function for getting this output. someone please guide me. Thanks in advance,
Active table:
Categoryid | Produtid
-----------+---------
1 1
Inactive table:
Categoryid | Produtid
-----------+----------
1 5
1 6
For inserting:
INSERT INTO InactiveTable
SELECT * FROM ActiveTable WHERE RowId = "<insert rowid>"
For deleting:
DELETE FROM ActiveTable
WHERE RowId = "<insert rowid>"
Obviously insert before you delete.
First of, I'd suggest you use an Active/Inactive flag (just add a bit to your table).
If that's really not what you want, you can write an SQL-trigger. Should look something like this:
CREATE TRIGGER dbo.SetActiveProductToInactive
ON dbo.ActiveProducts
FOR DELETE
AS
INSERT INTO dbo.InactiveProducts
SELECT * FROM deleted
GO
This inserts all deleted items into your ActiveProducst table before actually deleting them. If this is too much for what you are trying to accomplish, you should look at James' answer.
when you delete row it returns record. Try this.
Creating new table:
CREATE TABLE archived_table_timestamp AS WITH deleted_rows as
(DELETE FROM main_table RETURNING *)SELECT * FROM deleted_rows;
to insert in existing table:
WITH deleted_rows as (
DELETE FROM active_table WHERE 'condition' RETURNING *
)
INSERT INTO archived_table SELECT * FROM deleted_rows;
As #Nick.McDermaid mentioned in the comments it would be better to have Inactive flag on the product table. But if you still need to move these rows between to tables you can use OUTPUT clause to do that just in a single statement.
First we are creating these to tables
create table #Active (Categoryid int, Productid int);
create table #Inactive (Categoryid int, Productid int);
Second we are inserting these records
insert into #Active (Categoryid, Productid) values (1, 1), (1, 5), (1, 6);
Third we are deleting some rows from #Active table and inserting them to the #Passive table
delete t
output deleted.*
into #Inactive
from #Active AS t
where t.Productid in (5, 6);
If you need much more details about OUTPUT clause you can visit that link:
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql

Detect changes between records in two tables

I have 3 tables:
Staging: that gets employee records inserted every month.
Master: table has contains all previously entered records from staging, unique records.
Changes: keeps track of all changes - has no primary key.
The tables have 10 columns. In the staging table, every month we have about 2,500,000 records. Using a cursor I am able to insert new records from staging into the master table.
When it comes to update, I am using an inner join to get the records from staging that already exist in the master table.
To find out if any of the employee info has changed, do I have to query something line this:
WHERE Staging.FirstName <> Master.FirstName
OR Staging.LastName <> Master.LastName
OR ...
And so on for 10 columns, or is there an easier way?
If the two tables really are identical, you could create a persisted computed column in each table that represents a checksum of the entire row (see http://technet.microsoft.com/en-us/library/ms189788.aspx), create an index on that, and then use that for your joins.
Using a Cursor for millions of rows does not sound like fun.
Maybe you should look at EXCEPT/MERGE
WITH NewAndChanged AS (
SELECT Stage.Id
,Stage.Col1
,Stage.Col2
FROM Stage
EXCEPT
SELECT Master.Id
,Master.Col1
,Master.Col2
FROM Master
)
MERGE Master
USING NewAndChanged
ON Master.Id = NewAndChanged.Id
WHEN MATCHED
THEN UPDATE SET
Col1 = NewAndChanged.Col1
,Col2 = NewAndChanged.Col2
WHEN NOT MATCHED
THEN INSERT (
Id
,Col1
,Col2
)
VALUES (
NewAndChanged.Id
,NewAndChanged.Col1
,NewAndChanged.Col2
)

Multiple identity columns or a way to auto increment

I have a table (tOrder) that has the following structure in SQL Server 2008
orderID (int) - this is currently the primary key and the identity field.
name(varchar)
address(varchar)
groupID (int) - now this field i need to also auto increment, but at the same time i want to be able to insert values into.
My data would look something like:
1 - john - address1 - 1
2 - mary - address2 - 1
3 - mary -address3 - 2
4 - jane - address4 - 3
where order IDs 1 and 2 share the same group , while 3 and 4 are in their own.
Many orders can have same groupID, but when I insert an order of a new group, I would like the groupID to be auto populated with the next sequence number automatically, while at the same time allowing me to insert duplicate groupID for different orders if I need to.
Hope this makes sense.
How do I go about doing this? (I'm using c# in the back end, if that makes any difference)
I would create a new "groups" table with an identity to ensure uniqueness as follows:
create table tOrders(
orderID int PRIMARY KEY IDENTITY,
name varchar(30),
address varchar(60),
fkGroup int
);
create table tGroups(
groupID int PRIMARY KEY IDENTITY,
description varchar(50)
);
ALTER TABLE tOrders
ADD FOREIGN KEY (fkGroup) REFERENCES tGroups(groupID);
You would, of course have to either supply a groupID for the IDENTITY of a newly inserted tGroup (groupID) value.
This SQL Fiddle Example demonstrates one way of populating the tables.
One option would be to create a trigger on your torder table (not a fan of triggers, but given your criteria, can't think of another option).
CREATE TRIGGER tOrder_trigger
ON tOrder
AFTER INSERT
AS
UPDATE tOrder
SET groupid = (SELECT COALESCE(MAX(groupid),0) + 1 FROM tOrder)
FROM INSERTED AS I
WHERE I.groupid IS NULL
AND tOrder.orderid = I.orderid;
SQL Fiddle Demo
This checks if the inserted record has a NULL groupid using INSERTED, and if so, updates the table to the MAX(groupid) + 1, using COALESCE to check for NULL.

insert data into two table depending on the id from another table

I have table called customers contain custID,custName, another table called products contain proID,proName,price and third table Cust_PRo contain id,custID,proID.
i filled the products with data like this:
proID proName price
1 potato 100
2 cotton 600
3 rice 200
and in another form i have combobox i filled it with products names and textbox to write the customer name and gridview to appear data and there are two buttons one to add the values into grid and second to save it into database.
when i write the customer name and choose the products the data appear in the grid like this:
custName ProName
john potato
john cotton
john rice
as you see one customer can take many products the problem is to add the values into database i want when the user click the save button the data insert into the database like this:
first customers table:
custID custName
1 john
second Cust_PRo table:
id custID ProID
1 1 1
2 1 2
3 1 3
thank you
i'm not sure i got you 100% but i think you need some algorithm or something.. anyway
first, you need to generate a CustID for your new customer, to do that you need to get the maximum CustID from the table Customers and add it to 1 to avoid Primary key violation.
select max(CustID) from Customers
then, you'll be good to go. You have (CustID and ProdID from comboBox1.SelectedValue;)
I added the values to datatable and then used the SqlBulkCopy class to insert these values into database

how to display the items in the combobox in any given manner?

I have a dropdown getting populated by fetching a query on the database.
Say it fetches items given as follows:
Teacher,
Student,
Pricipal,
Sweeper,
FinanceManager.
While showing it in the dropdown, I wish to show it in the following order:
Principal,
FinanceManager,
Teacher,
Student,
Sweeper.
This isn't any specific order (ascending or descending), but just a order that has some relevance according to the personalities.
How do I acheive ?
Since you fetching the data from database,the easy solution to me is adding a extra column to the same table which hold order.
eg. Your Table
Column1 Column2 .... DisplayOrder(int)
Principal 1
FinanceManager 2
etc...
So you can order by the DisplayOrder when you do the selection
you could give them an extra "role-flag" in your db
ID NAME FLAG
1 Principal 5
3 FinanceM 4
33 Teacher 3
22 Student 2
99 Sweeper 1
and you could do the query by "order by FLAG"

Categories