Inserting a Row in a Table from Select Query - sql

I'm using two Stored Procedures and two Table in My Sql Server.
First Table Structure.
Second Table Structure.
When a Customer books a Order then the Data will be Inserted in Table 1.
I'm using a Select Query in another Page Which Selects the Details from the Second Table.
If a row with a billno from first table is not Present in Second Table I want to Insert into the Second Table with some Default Values in the Select Query. How can I do this
??

If you want to insert in the same query, you will have to create a stored procedure. There you'll query if row exists in second table, and, if not, insert a new entity in second table.
Your code should look something like this:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`table`#`%` PROCEDURE `insertBill`(IN billNo int, val1 int, val2 int, val3 int)
BEGIN
DECLARE totalres INT DEFAULT 0;
select count(*) from SECOND_TABLE where Bill_Number = billNo INTO totalres;
IF totalres < 1 THEN
INSERT into SECOND_TABLE values(val1,val2,val3);
END IF;
END
Val1,val2 and val3 are the valuest to be inserted into second table.
Hope this helps.

What you do is to LEFT JOIN the two tables and then select only the ones where the second table had no row to join, meaning the bill number were missing.
In the example below, you can replace #default_inform_status and #default_response_status with your default values.
INSERT INTO second_table (Bill_Number, Rest_Inform_Status, Rest_Response_Status)
SELECT ft.Bill_Number, #default_inform_status, #default_response_status
FROM first_table ft
LEFT JOIN second_table st
ON st.Bill_Number = ft.Bill_number
WHERE st.Bill_Number IS NULL
If it is possible to have duplicates of the same Bill_Number in the first table, you should also add a DISTINCT after the SELECT. But considering the fact that it is a primary key, this is no issue for you.

Related

Creating a table populated with record counts from other tables

I want to validate that 2 (or more) tables have the same count daily. I figured executing a SELECT count against each table and reporting them as values in their own named column within a temp table would be efficient even if just to eye-ball the numbers in the results window
CREATE TABLE #sync_count (mst_cnt AS varchar(5), info_cnt AS varchar(5));
INSERT INTO #sync_count (mst_cnt, info_cnt)
VALUES (
SELECT Sum(SRV_MST.SRV_MACID) AS mst_cnt FROM SRV_MST,
SELECT Sum(SRV_INFO.SRV_MACID) AS info_cnt FROM SRV_INFO,
))
DELETE #sync_count
Desired output
SRV_MST | SRV_INFO
===================
22 | 22
===================
Not sure exactly where I went wrong. Any tips? Many thanks
You need parentheses around subqueries:
CREATE TABLE #sync_count (mst_cnt varchar(5), info_cnt varchar(5));
----------------------------------^ as is not used in table declarations.
INSERT INTO #sync_count (mst_cnt, info_cnt)
VALUES ( (SELECT Sum(SRV_MST.SRV_MACID) AS mst_cnt FROM SRV_MST),
(SELECT Sum(SRV_INFO.SRV_MACID) AS info_cnt FROM SRV_INFO)
);
You also had an extra comma before the last paren.
I would strongly, strongly, strongly recommend that you define the counts as numbers and not string!
CREATE TABLE #sync_count (mst_cnt int, info_cnt int);
In fact, you can dispense with the table declaration and just use:
SELECT (SELECT Sum(SRV_MST.SRV_MACID) FROM SRV_MST) AS mst_cnt,
(SELECT Sum(SRV_INFO.SRV_MACID) FROM SRV_INFO) AS info_cnt
INTO #sync_count ;
You could write this as:
INSERT INTO #sync_count (mst_cnt, info_cnt)
SELECT
(SELECT Sum(SRV_MST.SRV_MACID) FROM SRV_MST),
(SELECT Sum(SRV_INFO.SRV_MACID) FROM SRV_INFO)

Update tables in one database from multiple tables in another database regularly

I have 2 databases in SQL Server, DB1 has multiple tables and some of the tables are updated with new records continuously. DB2 has only 1 table which should contain all the combined info from the multiple tables in DB1, and needs to be updated every 2 hours.
For example, DB1 has 3 tables: "ProductInfo", "StationRecord", "StationInfo". The first 2 tables both have a timestamp column that indicates when a record is created (i.e. the two tables are updated asynchronously, ONLY when a product passes all stations in "StationRecord" will "ProductInfo" be updated with a new product), and the last table is fixed.
The tables are as follows:
USE DB1
GO
CREATE TABLE ProductInfo
ProductID bigint Primary Key NOT NULL
TimeCreated datetime
ProductName nvarchar(255)
CREATE TABLE StationRecord
RecordID bigint Primary Key NOT NULL
TimeCreated datetime
ProductID bigint NOT NULL
StationID bigint
CREATE TABLE StationInfo
StationID bigint Primary Key NOT NULL
BOM_used nvarchar(255)
DB2 has only 1 table which contains a composite PK of "ProductID" & "StationID", as follows:
CREATE TABLE DB2.BOMHistory AS
SELECT
DB1.ProductInfo.ProductID
DB1.ProductInfo.TimeCreated AS ProductCreated
DB1.StationInfo.StationID
DB1.StationInfo.BOM_used
FROM DB1.ProductInfo
JOIN DB1.StationRecord
ON DB1.ProductInfo.ProductID = DB1.StationRecord.ProductID
JOIN DB1.StationInfo
ON DB1.StationRecord.StationID = DB1.StationInfo.StationID
constraint PK_BOMHistory Primary Key (ProductID,StationID)
I figured out the timing portion which is to use create a job with some pre-set schedules, and the job is to execute a stored procedure. The problem is how to write the stored procedure properly, which has to do the following things:
wait for the last product to pass all stations (and the "stationInfo" table is updated fully)
find all NEW records generated in this cycle in the tables in DB1
combine the information of the 3 tables in DB1
insert the combined info into DB2.BOMHistory
Here's my code:
ALTER Procedure BOMHistory_Proc
BEGIN
SELECT
DB1.ProductInfo.ProductID,
DB1.ProductInfo.TimeCreated AS ProductCreated
DB1.StationInfo.StationID,
DB1.StationInfo.BOM_used
into #temp_BOMList
FROM DB1.ProductInfo
JOIN DB1.StationRecord
ON DB1.ProductInfo.ProductID = DB1.StationRecord.ProductID
JOIN DB1.StationInfo
ON DB1.StationRecord.StationID = DB1.StationInfo.StationID
ORDER BY ProductInfo.ProductID
END
SELECT * from #temp_BOMList
INSERT INTO DB2.BOMHistory(ProductID, ProductCreated, StationID, BOM_used)
SELECT DISTINCT (ProductID, stationID)
FROM #temp_BOMList
WHERE (ProductID, stationID) NOT IN (SELECT ProductID, stationID FROM DB2.BOMHistory)
The Condition in the INSERT statement is not working, please provide some advice.
Also, should I use a table variable or a temp table for this application?
Try:
INSERT INTO DB2.BOMHistory(ProductID, ProductCreated, StationID, BOM_used)
SELECT DISTINCT tb.ProductID, tb.ProductCreated, tb.StationID, tb.BOM_used
FROM #temp_BOMList tb
WHERE NOT EXISTS
(SELECT * FROM DB2.BOMHistory WHERE ProductID = tb.ProductID AND StationID = tb.StationID)

Will order by preserve?

create table source_table (id number);
insert into source_table values(3);
insert into source_table values(1);
insert into source_table values(2);
create table target_table (id number, seq_val number);
create sequence example_sequence;
insert into target_table
select id, example_sequence.nextval
from
> (select id from source_table ***order by id***);
Is it officially assured that for the id's with the lower values in source_table corresponding sequence's value will also be lower when inserting into the source_table? In other words, is it guaranteed that the sorting provided by order by clause will be preserved when inserting?
EDIT
The question is not: 'Are rows ordered in a table as such?' but rather 'Can we rely on the order by clause used in the subquery when inserting?'.
To even more closely illustrate this, the contents of the target table in the above example, after running the query like select * from target_table order by id would be:
ID | SEQ_VAL
1 1
2 2
3 3
Moreover, if i specified descending ordering when inserting like this:
insert into target_table
select id, example_sequence.nextval
from
> (select id from source_table ***order by id DESC***);
The output of the same query from above would be:
ID | SEQ_VAL
1 3
2 2
3 1
Of that I'm sure, I have tested it multiple times. My question is 'Can I always rely on this ordering?'
Tables in a relational database are not ordered, and any apparent ordering in the result set of a cursor which lacks an ORDER BY is an artifact of data storage, is not guaranteed, and later actions on the table may cause this apparent ordering to change. If you want the results of a cursor to be ordered in a particular manner you MUST use an ORDER BY.

Update a table and insert missing records

I have a table with a foreign key column with some NULL records. I can select the records with missing column such as:
SELECT * FROM Outgoing WHERE Receipt_Id IS NULL
Now for each of these records I want to insert a new record in the table Receipts, get the inserted record's Id and set it as the value for Receipt_Id in this record.
Is this possible in a query?
It seems you are looking for inserted table
INSERT INTO Receipts (col1, col2....)
OUTPUT INSERTED.*
INTO #CreatedIds -- TEMP TABLE WHICH HOLDS RECENTLY INERTED DATA INCLUDING Receipt_Id (pk)
SELECT col1, col2....
FROM Outgoing
WHERE Receipt_Id IS NULL
To, see recently inserted records
SELECT c.*
FROM #CreatedIds c -- Note this is a table variable that you need to manual create.
Update: Since you are using Receipt table only as a sequence table. You should follow the updated approach which uses Sequences
Updated Answer:
All you need to do is to create a sequence say Receipts instead of a table with one column. And then update the Outgoing table with sequence numbers.
--create table Outgoing ( id int Primary Key IDENTITY(1,1),data nvarchar(100), record_id int);
--insert into Outgoing values ('john',NULL),('jane',NULL),('jean',NULL);
create sequence dbo.receipts as int start with 1 increment by 1;
update Outgoing
set record_id= NEXT VALUE FOR dbo.receipts
where record_id is null
select * from Outgoing
See working demo
Old Answer below
If you have ID column in both tables you can update Receipt_Id based on this column back into the Outgoing table
So you steps are :
1. insert records
DECLARE #LastRID bigint
SELECT #LastRID= MAX(Id) FROM Receipts
INSERT INTO Receipts(<col list>)
SELECT <col list> FROM Outgoing WHERE Receipt_Id IS NULL
update records based on uniqueness of all columns inserted from Outgoing to receipts using CHECKSUM function
update O
set O.Receipt_Id=R.Id
From Outgoing O
Join Receipts R
on CHECKSUM(o.<col list>)=CHECKSUM(R.<col list>)
and R.Id>#LastRID

Call function that returns table in a view in SQL Server 2000

SQL Server - Compatibility Level 2000
Person table - PersonId, PersonName, etc.. (~1200 records)
Two user functions - GetPersonAddress(#PersonId), GetPaymentAddress(#PersonId)
These two functions return data in a table with Street, City etc...(one record in the return table for the PersonId)
I have to create a view that joins the person table with these two user functions by passing in the person id.
Limitations:
Cross Apply is not supported on a function in SQL Server 2000
Cursor, temp table and temp variables are not supported in views so that I can loop upon the person table and call the functions.
Can someone help?
You could create functions GetPeopleAddresses() and GetPaymentsAddresses() which return PersonId as a field and then you can use them in JOIN:
SELECT t.PersonId, PersonName, etc..., a1.Address, a2.Address
FROM YourTable t
LEFT JOIN GetPeopleAddresses() a1 ON a1.PersonId = t.PersonId
LEFT JOIN GetPaymentsAddresses() a2 ON a2.PersonId = t.PersonId
Of course, your functions have to return only unique records
I'm afraid that you can't do that with a view in SQL Server 2000 because of the limitations you listed. The next best option as suggested in the comments is a stored procedure that returns the rows that would return the view.
If you need to use the results of the procedure in another query, you can insert the values returned by the procedure in a temporal table. Is not pretty, and you have to make two DB calls (one for creating/populating the temp table, and the other for using it), but it works. For example:
create table #TempResults (
PersonID int not null,
Name varchar(100),
Street varchar(100),
City varchar(100),
<all the other fields>
constraint primary key PK_TempResults (PersonID)
)
insert into #TempResults
exec spTheProcedureThatReplaceTheView #thePersonID
go -- end of the first DB call
select <fields>
from AnotherTable
join #TempResults on <condition>
-- don't forget to drop table when you don't need its current data anymore
drop table #TempResults