In foxpro, I can simply do this to add or merge table with different locations:
-> use C:\tableA
-> append from D:\tableB
in this foxpro code I've provided, tableB which exists from location D:\ appends all its row into tableA.
The question now is, how do I do that in C#?
I can simply invoke this query: insert into tableA select * from tableB to append all rows from tableB to tableA. But this is only true when I used same database and their file location remained intact and same at the same time.
My problem is that the database location of these two tables were different. How do I resolve this problem using C#?
looking to linq statements. What kind of database is this? http://social.msdn.microsoft.com/Forums/en-US/172b4f22-8c6e-4186-9ff4-e593fbda7566/can-i-use-linq-or-sqlstatements-to-transfer-values-from-one-table-to-another?forum=lightswitchgeneral
Related
I need to do a BULK INSERT of several hundred-thousand records across 3 tables. A simple breakdown of the tables would be:
TableA
--------
TableAID (PK)
TableBID (FK)
TableCID (FK)
Other Columns
TableB
--------
TableBID (PK)
Other Columns
TableC
--------
TableCID (PK)
Other Columns
The problem with a bulk insert, of course, is that it only works with one table so FK's become a problem.
I've been looking around for ways to work around this, and from what I've gleaned from various sources, using a SEQUENCE column might be the best bet. I just want to make sure I have correctly cobbled together the logic from the various threads and posts I've read on this. Let me know if I have the right idea.
First, would modify the tables to look like this:
TableA
--------
TableAID (PK)
TableBSequence
TableCSequence
Other Columns
TableB
--------
TableBID (PK)
TableBSequence
Other Columns
TableC
--------
TableCID (PK)
TableCSequence
Other Columns
Then, from within the application code, I would make five calls to the database with the following logic:
Request X Sequence numbers from TableC, where X is the known number of records to be inserted into TableC. (1st DB call.)
Request Y Sequence numbers from TableB, where Y is the known number of records to be inserted into TableB (2nd DB call.)
Modify the existing objects for A, B and C (which are models generated to mirror the tables) with the now known Sequence numbers.
Bulk insert to TableA. (3rd DB call)
Bulk insert to TableB. (4th DB call)
Bulk insert to TableC. (5th DB call)
And then, of course, we would always join on the Sequence.
I have three questions:
Do I have the basic logic correct?
In Tables B and C, would I remove the clustered index from the PK and put in on the Sequence instead?
Once the Sequence numbers are requested from Tables B and C, are they then somehow locked between the request and the bulk insert? I just need to make sure that between the request and the insert, some other process doesn't request and use the same numbers.
Thanks!
EDIT:
After typing this up and posting it, I've been reading deeper into the SEQUENCE document. I think I misunderstood it at first. SEQUENCE is not a column type. For the actual column in the table, I would just use an INT (or maybe a BIGINT) depending on the number of records I expect to have). The actual SEQUENCE object is an entirely separate entity whose job is to generate numeric values on request and keep track of which ones have already been generated. So, if I understand correctly, I would generate two SEQUENCE objects, one to be used in conjunction with Table B and one with Table C.
So that answers my third question.
Do I have the basic logic correct?
Yes. The other common approach here is to bulk load your data into a staging table, and do something similar on the server-side.
From the client you can request ranges of sequence values using the sp_sequence_get_range stored procedure.
In Tables B and C, would I remove the clustered index from the PK
No, as you later noted the sequence just supplies the PK values for you.
Sorry, read your question wrong at first. I see now that you are trying to generate your own PK's rather then allow MS SQL to generate them for you. Scratch my above comment.
As David Browne mentioned, you might want to use a staging table to avoid the strain you'll put on your app's heap. Use tempdb and do the modifications directly on the table using a single transaction for each table. Then, copy the staging tables over to their target or use a MERGE if appending. If you are enforcing FK's, you can temporarily remove those constraints if you choose to insert in reverse order (C=>B=>A). You also may want to consider temporarily removing indexes if experiencing performance issues during the insert. Last, consider using SSIS instead of a custom app.
I have several big CSV files that I need to import into SQL Server 2016 Express.
These files are related by identity keys, for instace each item in Documents.csv relate by Pkey to an item in Lines.csv by Fkey. Natural keys (for intance Document Number) are not allowed as there can be duplicates.
I've imported these files into a SQL Server staging tables, using SqlBulkCopy in C#. The screenshot shows the relations between these staging tables:
Table relations image
Now I need to copy these tables to the final ones, in this process I need to create surrogate keys and mantain the former Id and Fkey columns. I've read that this can be achieved with merge and output, but I don't understand it fully.
Already tried a couple of times and the results are wrong - can you help on this?
Edit:
These imports are going to be performed multiple time by clients at any given time, so I must ensure that there are no colisions with the relationships.
I've got the correct results for the tables Documents and Lines using the query below. Now the question is, how do I do this at the same time for all tables (Files, DocumentTotals, so on...)? In fact, the Files table relates to all tables in the Database, this part is confusing for me, because when I perform the merge of Documents_staging into Documents I have to have already perform the mapping of Files table to relate the Files.Id's with all FileId's of all tables, correct? Thanks!
declare #match table
(OriginalId int, insertedId int);
merge into dbo.Documents as tgt
using dbo.Documents_staging as src
on 1 != 1
when not matched then
insert
(Number, Date)
values
(src.Number, Date)
output
src.Id,
inserted.Id
into
#match;
insert into Lines (Fkey, Number, Product)
select m.insertedId
,lines.Number
,lines.Product
from
Lines_Staging as lines
left join #match m
on lines.Fkey = m.OriginalId
I am using EF 6 in my project, when i want to delete a row from a table it trow exception because that row is referenced in another table. I want to know which table preventing me from deleting with c# code and EF.
We have a record in table A and that row is referenced in table C not in table B. Is it possible with EF to know that table C prevent me from deleting that row?
I am also using Sql-Server 2012.
If you are trying to dynamically sort this at runtime to show the user or determine before delete attempt and you are unsure of the possible conflict you could use the sys tables and some dynamic sql to sort this out.
Use sys.objects to find your table name and get an object_id.
Use sys.foreign_keys to find tables that reference your table.
Use sys.foreign_key_columns to get the exact column numbers referenced.
Use sys.columns to get appropriate column names.
Build dynamic SQL to search the table and column names and find the offending rows using the values from the source row that cannot be deleted.
List the tables returned looking up in sys.objects. Optionally list the number of rows.
Optionally use dynamic SQL to build other statements (e.g. delete offending records - this may need to be recursive - take care with this - you could lose a lot of data!)
In my ASP.NET web app I'm trying to implement an import/export procedure to save or insert data in the application DB. My procedure generates some CSV files: one for each table.
Obviously there are relations between some of these tables and when I import CSV in my DB I'd like to maintain association between rows.
Say I have Table1 and Table2 with Table2 that has a foreign key to Table1. So I could have a row in Table1 with ID = 100 and a row in Table2 with Table1_ID = 100.
When I import CSV with Table1 data, new IDs are generated for Table1 rows, how can I maintain consistency of the foreign keys in Table2 when I import the corresponding CSV file?
I'm using Linq-to-SQL to retrieve data from DB... using DataSet and DataTable can help me?
NOTE I'd like to permit cumulative import, so when I import a CSV file there may already be data in the DB. So I cannot use 'Set Identity OFF'.
Add the items of Table1 first, so when you add the items of Table2 there are the corresponding records of Table1 already in the database. For more tables you will have figure out the order. If you are creating a system of arbitrary database schema, you will want to create a table graph (where each node is a table and each arc is a foreign key) in memory [There are no types for that in the base library] and then convert it to a tree such that you get the correct order by traversing the tree (breadth-first).
You can let the database handle the cases where there is a violation of the foreign key, because there is not such field. You will have to decide if you make a transaction of the whole import operation, or per item.
Although analisying the CSVs before hand is possible. To do that, you will want to store the values for the primary key of each table [Use a set for that] (again, iterate over the tables in the correct order), and then when you are reading a table that has a foreign key to a table that you have already read you can check if the key is there, also it will help you yo detect any possible duplicate. [If you have things already in the database to take into account, you would have to query too... although, take care if the database is in an active system where records could be deleted while you are still deciding if you can add the CSVs without problem].
To address that you are generating new IDs when you add...
The simplest solution that I can think of is: don't. In particular if it is an active system, where other requests are being processed, because then there is no way to predict the new IDs before hand. Your best bet would be to add them one by one, in that case, you will have to think your transaction strategy accordningly... it may be the case that you will not be able to roll back.
Although, I think your question is a bit deeper: If the ID of the Table1 did change, then how can I update the corresponding records in the Table2 so they point to the correct record in Table1?
To do that, I want to suggest to do the analysis as I described above, then you will have a group of sets that will works as indexes. This will help you locate the records that you need to update in Table2 for each ID in Table1. [It is also important to keep track if you have already updated a record, and don't do it twice, because it may happen the generated ID match an ID that is yet to be sent to the database].
To roll back, you can also use those sets, as they will end up having the new IDs that identify the records that you will have to pull out of the database if you want to abort the operation.
Edit: those sets (I recommend hashset) are only have the story, because they only have the primary key (for intance: ID in Table1). You will need bags to keep the foreing keys (in this case Table1_ID in Table2).
I've built a report with the report wizard in C#, and I can see my report in ReportViewer. My problem is that I have 2 tables that are related. The value of a column in the first table is a foreign key on the other table. All I see in that column is just the foreign key. I'd like to see the corresponding value from the other table.
How can I see value of the column from the second table?
You should just join on the foreign key columns:
SELECT
a.*,b.YourNeededColumnHere
FROM TableA a
INNER JOIN TableB b ON a.columnX=b.columnX
However, if you are having problems doing this in reporting services, just create a view:
CREATE VIEW CombinedAB
AS
SELECT
a.*,b.YourNeededColumnHere
FROM TableA a
INNER JOIN TableB b ON a.columnX=b.columnX
GO
you should now be able to run your report off the CombinedAB view as:
SELECT
*
FROM CombinedAB
WHERE ...your conditions here...
sounds like you probably need a drill down report
Create Basic Drilldown Report
Regarding the control that renders the result... Does it have its columns bound manually / is it set to auto-bind?
Change your query to one that involves the fields from the appropriate tables.
SELECT t1.*, t2.value
FROM table1 t1
JOIN table2 t2 ON t1.t2id = t2.id
But if you can't, because the data sources are separate, then you'll be wanting another option.
Assuming you have two datasets, from separate data sources.
Put a table in your report to show information from DataSet1 (or whatever it's called). Then put a rectangle in place of one of your textboxes, and then put a table in there, which you attach to DataSet2. Then put a filter on this table, so that it only shows records from DataSet2 which correspond to the appropriate value in DataSet1.
Or, wait for SQL Server 2008 R2 (currently in CTP), which provides a Lookup function for exactly this purpose.
Rob
Drag the item from the table where it's the Foreign Key, not it's native location.