Copy a dependent table - sql

I have this customers table (I'm using SQL Server):
About 300 customers were registered in this table. I created another table in another database and inserted these customers into the new database.
Here is the new customers table:
But I have an operation table as well and I didn't change this one. The problem is the foreign key here. Since PhoneNumber is no longer the primary key in Customers table, customerId shouldn't be filled with the phone number anymore. I want to know how can I insert about 1000 operations in the new operation table but use each customer's ID as a foreign key instead of phone number in customerId.
Here is the operations table:

You can use following query to update the old data in operation table:
UPDATE OperationTable AS OT SET CustomerID =
(SELECT ID FROM CustomerTable AS CT WHERE CT.PhoneNumber = OT.CustomerID)

Assuming Counter in the old database is same as CustomerId in new database.
In your previous operations table of the old database, write a query like below
select 'Insert into OperationsTable values(
' + CT.Counter + ',
' + OT.TypeID + ',
' + OT.Amount + ',
' + OT.DateTime + ')' as newquery from OperationTable OT left outer join Customers CT on CT.PhoneNumber=OT.PhoneNumber
This will give you the insert queries which can be copied and run on the new OperationsTable in the new database
Now - if the above assumption is not correct - then -
You will have to write a query on the new customer table to insert the new Id from new customer database into the Counter Column (or a new CID column) of the old customer database, and then repeat the above step.

If we assume that AFDB is the old database and StoreDB is the new one, the following query helped me out:
INSERT INTO StoreDB.dbo.Operations
SELECT StoreDB.dbo.Customers.Id, TypeID, Amount, [DateTime]
FROM AFDB.dbo.Operations JOIN StoreDB.dbo.Customers
ON StoreDb.dbo.Customers.PhoneNumber = AFDB.dbo.Operations.CustomerId;

Related

Inserting an ID that increments (but is not an AUTOINCREMENT)

I have a table that I am trying to insert multiple records into using a select statement.
The ID field is an INT and not autoincremented but I do need to increment in in the INSERT.
The table belongs to a third party product we use for our ERP so I cannot change the property of the ID.
The insert is supposed to create a record in the EXT01100 table for each line item on a particular sales order.
Here is the code I am using:
INSERT INTO EXT01100 (Extender_Record_ID, Extender_Window_ID, Extender_Key_Values_1 , Extender_Key_Values_2, Extender_Key_Values_3)
SELECT (SELECT MAX(EXTENDER_RECORD_ID) + 1 FROM EXT01100), 'ECO_FEE_DIGIT', SOL.LNITMSEQ, SOL.SOPNUMBE, SOL.SOPTYPE
FROM SOP10200 SOL WITH(NOLOCK)
WHERE SOL.SOPTYPE = #InTYPE AND SOL.SOPNUMBE = #INNUMBE AND SOL.LNITMSEQ <> 0
This works on a single line order, but multiple line orders will produce a Primary Key duplicate error so I don't think I can use (SELECT MAX(EXTENDER_RECORD_ID) + 1 FROM EXT01100) in this case.
This is in SQL server.
Any help is greatly appreciated!
You can use row_number to ensure each row has a unique ID, and you need to take an exclusive lock on your main sequence table, and you need to remove your nolock.
INSERT INTO EXT01100 (Extender_Record_ID, Extender_Window_ID, Extender_Key_Values_1 , Extender_Key_Values_2, Extender_Key_Values_3)
SELECT (SELECT MAX(EXTENDER_RECORD_ID) FROM EXT01100 WITH (TABLOCKX)) + ROW_NUMBER() OVER (ORDER BY SOL.LNITMSEQ)
, 'ECO_FEE_DIGIT', SOL.LNITMSEQ, SOL.SOPNUMBE, SOL.SOPTYPE
FROM SOP10200 SOL
WHERE SOL.SOPTYPE = #InTYPE AND SOL.SOPNUMBE = #INNUMBE AND SOL.LNITMSEQ <> 0;
Seconding a recommendation from the comments above, we use Sequences in our production system with no problem. Here's how it looks:
create sequence SQ_Extender_Record_ID
minvalue 1
start with 1
cache 100;
INSERT INTO EXT01100 (Extender_Record_ID, Extender_Window_ID, Extender_Key_Values_1 , Extender_Key_Values_2, Extender_Key_Values_3)
SELECT (next value for SQ_Extender_Record_ID), 'ECO_FEE_DIGIT', SOL.LNITMSEQ, SOL.SOPNUMBE, SOL.SOPTYPE
FROM SOP10200 SOL
WHERE SOL.SOPTYPE = #InTYPE AND SOL.SOPNUMBE = #INNUMBE AND SOL.LNITMSEQ <> 0
Obviously, adjust the min/start values as appropriate for your situation.
If you want, you could add a default constraint to the table/column with this:
alter table EXT01100 add constraint DF_EXT01100__Extender_Record_ID
default (next value for SQ_Extender_Record_ID)
for Extender_Record_ID
You mention that this is in a database whose schema you don't control, so that may not be an option; I mention it for the sake of completeness.

SQL insert trigger for insert with update

I have two tables:
[1] Donations - with amount and pet_id field
[2] Pets - with id and total donations field
I'm trying to create a trigger which will update total donations field whenever
a new row is being inserted to Donations table. I tried this one:
create trigger update_donations
on sponserships
for insert
as
update dbo.Pets
set tot_donations = (
select new_val = inserted.amount + pets.tot_donations
from inserted
where inserted.[Pet-ID] = pets.[Animal-ID]
)
But of course it changes all records, whereas i want to change only records that are changed in the donations table.
It is usually not a good practice to store this type of derived information - you could have a view that computes it on the fly rather than a trigger that keeps it up to date. Also please note that if you go that way, you also need a delete and an update trigger...
That said, you can use the following query in your insert trigger to update the relevant record in the pets table:
update p
set p.total_donations = p.total_donations + i.amount
from dbo.Pets p
inner join inserted i on i.[Pet-ID] = p.[Animal-ID]

Dynamically Updating Columns with new Data

I am handling an SQL table with over 10K+ Values, essentially it controls updating the status of a production station over the day. Currently the SQL server will report a new message at the current time stamp - ergo a new entry can be generated for the same part hundreds of times a day whilst only having the column "Production_Status" and "TimeStamp" changed. I want to create a new table that selects unique part names then have two other columns that control bringing up the LATEST entry for THAT part.
I have currently selected the data - reordered it so the latest timestamp is first on the list. I am currently trying to do this dynamic table but I am new to sql.
select dateTimeStamp,partNumber,lineStatus
from tblPLCData
where lineStatus like '_ Zone %' or lineStatus = 'Production'
order by dateTimeStamp desc;
The Expected results should be a NewTable with the row count being based off how many parts are in our total production facility - this column will be static - then two other columns that will check Originaltable for the latest status and timestamp and update the two other columns in the newTable.
I don't need help with the table creation but more the logic that surrounds the updating of rows based off of another table.
Much Appreciated.
It looks like you could take advantage of a sub join that finds the MAX statusDate for each partNumber, then joins back to itself so that you can get the corresponding lineStatus value that corresponds to the record with the max date. I just have you inserting/updating a temp table but this can be the general approach you could take.
-- New table that might already exist in your db, I am creating one here
declare #NewTable(
partNumber int,
lineStatus varchar(max),
last_update datetime
)
-- To initially set up your table or to update your table later with new part numbers that were not added before
insert into #NewTable
select tpd.partNumber, tpd.lineStatus, tpd.lineStatusdate
from tblPLCData tpd
join (
select partNumber, MAX(lineStatusdate) lineStatusDateMax
from tblPLCData
group by partNumber
) maxStatusDate on tpd.partNumber = maxStatusDate.partNumber
and tpd.lineStatusdate = maxStatusDate.lineStatusDateMax
left join #NewTable nt on tbd.partNumber = nt.partNumber
where tpd.lineStatus like '_ Zone %' or tpd.lineStatus = 'Production' and nt.partNumber is null
-- To update your table whenever you deem it necessary to refresh it. I try to avoid triggers in my dbs
update nt set nt.lineStatus = tpd.lineStatus, nt.lineStatusdate = tpd.lineStatusDate
from tblPLCData tpd
join (
select partNumber, MAX(lineStatusdate) lineStatusDateMax
from tblPLCData
group by partNumber
) maxStatusDate on tpd.partNumber = maxStatusDate.partNumber
and tpd.lineStatusdate = maxStatusDate.lineStatusDateMax
join #NewTable nt on tbd.partNumber = nt.partNumber
where tpd.lineStatus like '_ Zone %' or tpd.lineStatus = 'Production'

How to import values into a column from another table in Access

I created an Access Database and I wish to import a subset of data from a master table into a smaller table using SQL Queries. Basically, I want the smaller (Customer) table to reflect any changes made in the bigger (Total) table.
I tried the following code:
UPDATE Customer SET Brand =
(SELECT Brand FROM Total WHERE Chance = -1) ; Chance is a binary column
WHERE EXIST (SELECT Brand FROM Total WHERE Chance = -1);
, but I get an error: "operation must use an updateable query" and my file is not a read-only file.
Is there another Query that I can use to perform the same task?
Update statement in MS Access database should looks like:
UPDATE Customer AS C
INNER JOIN Total AS T ON T.PK = C.FK
SET C.Brand = T.Brand
WHERE T.Chance=-1;
Where:
PK = Primary Key
FK = Foreign Key

Database consistency check using SQL

I have the next problem:
The database in the system has denormalized tables with lets say "CompanyID" field held on almost every table in the database. This was done due to business rules purposes and should be that way. Sometimes the data is inconsistent as the Customer being with CompanyID == 1 has the order with CompanyID == 2.
My suggestion is to write specialized stored procedure which would be fired every once in a while and analyse some basic 'relation chains' on this property (meaning Cusomer with some Company ID should always have only Orders from the same Company ID where the latter has Articles with corresponding Company ID)
Quesqion:
Is there any generic way in SQL to fetch tables having field CompanyID and then checking them on consistency? Any other solutions to this problem?
I get the tables with the given column name using this SQL:
select column_name, c.is_nullable, c.table_schema, c.table_name, t.table_type, t.table_catalog, *
from information_schema.columns c join information_schema.tables t
on c.table_schema = t.table_schema and c.table_name = t.table_name
where column_name = 'CompanyID'
and table_type not in ('VIEW')
and t.table_name not like 'MsMerge%'
order by ordinal_position
After that I have in mind to traverse by foreign keys up the relation tree for record checking the equality of the CompanyID parameter.
I would not do that via a generic sql that runs every view minutes - this is the performance dead for big databases.
Instead you could use a Insert/Update Trigger on every effected table that you would code like that:
CREATE TRIGGER chk_tablename
ON T1 tablename
FOR INSERT,UPDATE
AS
BEGIN
// Your checks are here
// Log inconsistent data
END
example of query:
lets say these are our tables:
create table customer(
id int,
companyID int
)
create table orders (
orderId int,
customerid int,
companyID int --"wrong column"
)
you should tun queries like these:
update orders
set companyID=(select companyID from customer where id=customerid)
to correct the data, but also eliminate all usages of column companyID on table orders.
If you have loads of places where this is happening and you want to create an automate way of running the above query, you can look for the column companyID on the table sys.columns, get the table name from it and build a loop to generate the queries
EDIT (based on your answer on the comments):
so the logic is pretty much the same.
Loop through the sys.columns table to get the tables where the column appears and for each table run:
select *
from orders o
where companyID != (select companyID from customer where id=customerid)