C# and SQL - elegant way to generate script for several tables - c#

Im working on database synchronization in my app. It means I have 5 databases, but:
only in first database product could be added/removed/modified
this first database saving information about added/removed/modified product to table (with flag 1/2/3 as add/edit/remove and productID)
so first database generates INSERT script from SELECT, for example:
in my product_changes table (addedRemovedEdited INT, productID INT) I have information:
1, 15 (1 - flag means product with ID = 15 was added), or
2, 15 (2 - flag means product with ID = 15 was edited) etc.
Now using this information I can create script - and there is problem.
At this momment im creating scripts like:
SELECT (col1, col2, col3,...) FROM Product_Category;
string query = "INSERT INTO Table VALUES (#a,#b,#c)...";
SELECT (col1,col2,col3,...) FROM Product_price;
query += "INSERT INTO .......";
And I need to do it foreach tables which contains information about one single products. So for 10 products I'll have 10 * 12 (12 because there is ~12 tables about one product) blocks of code like INSERT INTO Table 1(....); INSERT INTO TABLE2(....).
Problem is also that, all data need to have same ID in every databases - so I'm using ##identity and put it into insert query. It has to be this way, because product with ID = 10 with name 'Keyboard' in mainDB = product with ID = 10 in DB10.
And the question - maybe some of you know any better (becouse that one is not so good) solution how can I create those scripts? Like query, which will take all information from my string[] a = {"Product", "Product_price", "Product_category"} tables and generate INSERT queries but - most important - where I can add ##identity.
#EDIT: I forgot. I found that solution: how i can generate programmatically "insert into" data script file from a database table?
Well, it does generate scripts, but with auto-incremented ID. And I need to add information in right order (as middle tables) for example:
INSERT INTO Product(.....) VALUES (...);
SET #pID = ##identity FROM Product;
INSERT INTO Price (priceID,.....) VALUES (...);
SET #prID = ##identity FROM Price;
INSERT INTO Product_price (priceID, productID,...) VALUES (#prID, #pID)

Related

how to insert same LAST_INSERT_ID() in one table to create multiple records;

I am programming a website, with ASP.NET, C#, as well as using MYSQL.
I need to be able to record two rows with same child_id;
My problem is with this one statement, it inserts one row and skips the last.
//data.ChldrenRecord.Service contain two records
// babysit, and tutor
foreach (string s in data.ChildrenRecord.Services)
{
query += (" INSERT INTO ServiceChildren SET service='" + s + "', child_id=LAST_INSERT_ID();");
}
so table should look something like this
id service child_id
1 babysit 1
2 tutor 1
I use Last_INSERT_ID() because child_id is a foreign key. I create a record in another table whose primary key is child_id. Afterwards, I use LAST_INSERT_ID() to reference that one record primary key child_id so that i may use it in my ServiceChildren table.
as it stands my table looks:
id service child_id
1 babysit 1
I think i am on the right track now. if i log directly into the database, this statement works:
SET #last_id = LAST_INSERT_ID();
//then insert statements
INSERT INTO ServiceChildren(service, child_id) VALUES('babysit', #last_id);
INSERT INTO ServiceChildren(service, child_id) VALUES('tutor', #last_id);
BUT IN MY C#, ASP.NET CODE THE LINE
SET #last_id = LAST_INSERT_ID();
does not do anything, even populate tables with a prior insert statement.
OK, I found out my problem. I needed to place Allow User Variables=True in the connection string to be allowed to create and use #last_id.

How to reorder auto increment column values, after deleting any row other than last row?

I want to know is there any SQL query for asp.net,c# that can just re arrange auto increment coloumn values..
eg.
deleting 2 in the table:
sno
1
2
3
4
does:
sno
1
3
4
but i want re-arrangement:
sno
1
2
3
Note:
Don't want to to the numbering manually
query to create table is like this:
CREATE TABLE uid (sno int IDENTITY(1,1) PRIMARY KEY, qpname nvarchar(500), mob int, tm int)
Let your table be named Parent and table that will hold the backup is called Backup. They should have identical columns.
INSERT INTO dbo.Backup
SELECT * FROM dbo.Parent
Now truncate the parent table
TRUNCATE TABLE dbo.Parent
Now you can just insert the data back using the first command and just reversing the table names.
Remember that this may not work in all cases. You may have On delete cascade on and if that is the case, then you would loose all data from other tables also which are referencing the parent table. I think that you should never use this is you are using any Foriegn Key reference on this table.
Following are the queries which should run 1 after other to get this functionality done. This can be easily achieved in C# by executing a generic ExecuteNonQuery().
DELETE FROM TBL1 WHERE sno = #sno;
UPDATE TBL1
SET sno = sno -1
WHERE sno > #sno;

Update a field 'version' into a table

I have this situation:
I have two tables:
Table A
Staging_Table A
Both tables contain those common columns:
Code
Description
Into Table A I also have a column Version which identifies the last version of corresponding column Code.
My problem is how to update the column Version once a new Description is stored for the same Code (I fill up the Staging_Table with a bulk Insert from C#. I have a flow of data that change once a week).
I need to insert the new row into Table A which contain the same Code, but a different Description, without deleting the old one.
I insert the rows from Staging table to table A with MINUS operation and I have this mechanism within a stored procedure because I also fill up the staging table with a Bulk Insert from C#.
The result I need to obtain is the following:
TABLE A:
Id Code Description Version End_date
-- ----------------- ------- --------
1 8585 Red Car 1 26-mag-2015
2 8585 Red Car RRRR 2 01-giu-2015
How can I do that?
I hope the issue is clear
If I understand correctly process work like that:
1. Data is loaded to staging table Staging_table_A
2. Data is inserted from Staging_table_A itno Table_A with additional column version.
I would do:
with cnt as (select count(*) c, code from Table_A group by code)
Insert into Table_A (select sta.*, nvl(cnt.c,0) + 1 as version
from Staging_table_A sta left outer join cnt on (sta.code = cnt.code));
This is based on condition that in Table_A versions contains no duplicates.

Get MAX id number from database table after deleting last record

I want to get a new row id for "products", for this I use MAX SQL command as follwing (the command is in insert new record button click event):
SqlCommand cmd = new SqlCommand("Select ISNULL(MAX(id)+1,0) from products", SqlCon);
the issue is when there are rows with IDs 10,11,12 (12 is MAX) and i delete id 12 record , i gets MAX+1 id 12 when the new id row is 13 ("id" field is PK with identity increment 1).
can i do it with other way?
example:
id prodect
-- -------
1 dog
2 cat
3 mouse
4 elefant
when i deletes row 4 i get MAX(id)+1 = 4 and i want to get 5 since this is the next row id.
I suspect the actual question is How can I find the ID of the row I just inserted so I can use it as a foreign key in related tables or in an image file name?
SQL Server since 2005 provides the OUTPUT clause in INSERT, UPDATE, DELETE statements that returns the values of the columns just inserted or modified. In the case of the insert statement, the syntax is:
insert into Products (Product)
OUTPUT inserted.ID
VALUES ('xxx')
This is a better option than the IDENT_CURRENT or SCOPE_IDENTITY values because it returns the values using a single statement and there is no ambiguity about what is returned:
IDENT_CURRENT may return a different value if multiple users are writing to the table outside a transaction
SCOPE_IDENTITY returns the last ID generated in a transaction, no matter the table
You can return more than one column:
insert into Products (Product)
OUTPUT inserted.ID, inserted.Product
VALUES ('xxx')
You can execute this statement with ExecuteScalar, if you return only one column or ExecuteReader, if you want to return more columns.
In the case of UPDATE or DELETE statements, the deleted table contains the deleted values and inserted contains the new values
Note ORMs like Entity Framework use such statements already to retrieve auto-generated IDs and update saved objects. In this case one only needs to read the ID property of the saved objects.
I will take a stab at what I think you are after. :)
If you include SELECT SCOPE_IDENTITY(); in your SQL you will get the ID you need:
INSERT INTO products (
* your fields *
)
VALUES (
* your values *
);
SELECT SCOPE_IDENTITY();
And then in your code you can have:
var Id = Convert.ToInt32(cmd.ExecuteScalar());
This will give you the id of the record you have inserted.
One possible solution could be that you don't delete the rows. You can add a flag and make it inactive/deleted. That way your row numbers will always be preserved and your code will give you the max Id.
I think the OP tries to tackle the wrong problem...
When you insert a new product into the products table, you should try to retrieve the new id directly with the scope_identity function as such (SQLServer!):
string sql = "insert into products(name) values('Yellow Cup'); SELECT SCOPE_IDENTITY();";
var sqlCommand = new SqlCommand(sql, conn);
var id = cSqlServer.ExecuteScalar();
Definitely MAX is not what anybody would use in this case. Closest solution would be to get recently used identity value and then increment it by 1 (in your case) or by seed value, whatever it is.
select ident_current('products') + 1
Caution - although this solves your purpose for now, beware that 'ident_current' will return you the identity value set by other sessions as well. In simple words, if there is some request/trigger/execution that causes id to be incremented even before your button click finishes then you you will get inserted_id and not deleted one.

C# list items to database SQL

Hello I have a simple question that regards inserting data into a MS MySql Database 2012 table. The table that I have is called COMPLETED and has 3 fields.
student_ID (int, NOT allowed nulls)
completed (bool, NOT allowed nulls)
random_code (string, allowed nulls)
In c# I have a list filled with unique random codes. I want all codes inserted into the database, so if I have 20 records I want 20 unique codes inserted into the random_code field. So the first records gets the first code, the seconds records gets the second code and so on. I think the best way to do this is using a foreach and, for each code in the list of codes insert that code into the random_code field in my database. The problem is I don't know how to do this. I have the following code that give's me an error at VALUE:
Incorrect syntax near 'VALUE'.
foreach (string unRaCo in codes)
{
//insert database
SqlCommand toDB = new SqlCommand("INSERT INTO COMPLETED (random_code) VALUE ( '"+ unRaCo +"' ) ", conn);
SqlDataReader toDBR;
toDBR = toDB.ExecuteReader();
}
Could anyone give me a dircetion here? Thanks in advance.
EDIT:
Okay I totally changed my query as I figured out it did not yet do what I wanted it to do. I now want to update my records instead of inserting records. I did that with the following code:
foreach (string unRaCo in codes)
{
//insert database
SqlCommand naarDB = new SqlCommand("UPDATE VOLTOOID SET random_code = '"+ unRaCo +"' ", connectie);
SqlDataReader naarDBR;
naarDBR = naarDB.ExecuteReader();
naarDBR.Close();
}
The problem this time is that the update query updates ALL records with the first code, so the first record has the code 12345 for example but all other records also have that code. I want to update 12345 into record 1 and 54321 for example in number 2, how do I do that?
The correct is Values not Value, even if you only provide one column.
About your edit. First of all beware of SQL Injection. You better use SQLParameter class. Check Configuring Parameters and Parameter Data Types for further info.
If you want to update a specific id then use a where clause like (in plain SQL):
UPDATE VOLTOOID SET random_code = #NewValue WHERE random_code = #OldValue
Now if you just want to add the random number in a specific row, then you would have to use some more advanced SQL functions. Again in plain SQL you would have:
;WITH MyCTE AS
(
SELECT random_code,
ROW_NUMBER() OVER(ORDER BY random_code) AS ROWSEQ -- This will give a unique row number to each row of your table
FROM VOLTOOID _code
)
UPDATE MyCTE
SET random_code = #NewValue
WHERE ROWSEQ = #YourRandomRow
As the above queries are for SQL script execution you will need to define the variable used.
Your syntax is wrong, you are using 'value' where you should use 'values'. If you have SSMS you will able to easily figure out this kind of errors.
Usually I create the query in SQL Server Management Studio query editor, then use it in C#. Most of the times I use SQL Server stored procedures where it's possible. Because I think it cost some extra resources to execute a text query than executing a procedure

Categories

Resources