Sequence in sql operation? - asp.net

I am passing datatable as input parameter to stored procedure. Datatable contains id, Name,Lname,Mobileno,EmpId.
Employee table contains [Name],[Lname],[mobno],[Did] as columns.
When user is logged in, his Id come as DId. There are more than 1000 records. Instead of passing that id to datatable, I have created
separete parameter to sp. I want to add records to Employee table, which are not already exist. If combination of mobileno and Did already exists, then
don't insert into Employee table, else insert. Datatable may contain records, which can be duplicate. So I don't want to include that record. I want select only
distinct records and add them to table. I am intrested in mobile no. If there are 10 record having same moble no, I am fetching record, which comes first.
Following code is right or wrong. According to my knowledge, first from clause, then inner join, then where, then select execute. Record get fetched from datatable,
then inner join happens generate result, from that result not from datatable it will check record. So it will give me proper output.
Create Procedure Proc_InsertEmpDetails
#tblEmp EmpType READONLY,
#DId int
as
begin
INSERT INTO Employee
([Name],[Lname],[mobno],[Did])
SELECT [Name],[Lname],[mobno] #DId
FROM #tblEmp A
Inner join (
select min(Id) as minID, mobno from #tblEmp group by mobno
) MinIDTbl
on MinIDTbl.minID = A.ExcelId
WHERE NOT EXISTS (SELECT 1
FROM Employee B
WHERE B.[mobno] = A.[mobno]
AND B.[Did] = #DId )
end
or does I need to change like this
INSERT INTO Employee
([Name],[Lname],[mobno],[Did])
SELECT C.[Name],C.[Lname],C.[mobno], C.D_Id
from
(SELECT [Name],[Lname],[mobno] #DId as D_Id
FROM #tblEmp A
Inner join (
select min(Id) as minID, mobno from #tblEmp group by mobno
) MinIDTbl
on MinIDTbl.minID = A.ExcelId
)C
WHERE NOT EXISTS (SELECT 1
FROM Employee B
WHERE B.[mobno] = C.[mobno]
AND B.[Did] = #DId )

Related

Oracle 11g Triggers

I have create a table person(id, name ,samenamecount).The samenamecount attribute can be null but for each row can store the row count for same names.I am achieving this by calling a stored procedure inside a after insert trigger.Below is my code.
create or replace procedure automatic(s in person.name%type)
AS
BEGIN
update person set samenamecount=(select count(*) from person where name=s) where name=s;
END;
create or replace trigger inserttrigger
after insert
on person
for each row
declare
begin
automatic(:new.name);
end;
On inserting a row it is giving error like
table ABCD.PERSON is mutating, trigger/function may not see it.
Can somebody help me to figure out this?
If you have the table:
CREATE TABLE person (
id NUMBER
GENERATED ALWAYS AS IDENTITY
CONSTRAINT person__id__pk PRIMARY KEY,
name VARCHAR2(20)
NOT NULL
);
Then rather than creating a trigger, instead, you could use a view:
CREATE VIEW person_view (
id,
name,
samenamecount
) AS
SELECT id,
name,
COUNT(*) OVER (PARTITION BY name)
FROM person;
You can use the trigger:
CREATE TRIGGER inserttrigger
AFTER INSERT ON person
BEGIN
MERGE INTO person dst
USING (
SELECT ROWID AS rid,
COUNT(*) OVER (PARTITION BY name) AS cnt
FROM person
) src
ON (src.rid = dst.ROWID)
WHEN MATCHED THEN
UPDATE SET samenamecount = src.cnt;
END;
/
fiddle
If you want to make it more efficient then you could use a compound trigger and collate the names that are being inserted and only update the matching rows.

Updating records with addition using sub queries in SQLite

I am attemping to update a record in table StockCatalog called Product Quantity by adding Product Quantity together with a record called DeliveryQuantity in table DeliveryContent whilst inner joining two records, StockCatalog.StockID = DeliveryContent.StockID inner joining DeliveryContent.DeliveryID = Deliveries.DeliveryID. So far I have this:
UPDATE StockCatalog
SET ProductQuantity = (SELECT StockCatalog.ProductQuantity FROM StockCatalog INNER JOIN DeliveryContent on StockCatalog.StockID = DeliveryContent.StockID WHERE StockCatalog.ProductQuantity + DeliveryContent.DeliveryQuantity)
WHERE (SELECT DeliveryContent.DeliveryID FROM DeliveryContent INNER JOIN Deliveries on DeliveryContent.DeliveryID = Deliveries.DeliveryID)
However it appears that this updates all ProductQuantity records in StockCatalog with one record of DeliveryQuantity in DeliveryContent. Sorry If this is confusing.
Seems to be some confusion about WHERE going on. I GUESS this is what you want:
UPDATE StockCatalog sc SET ProductQuantity = ProductQuantity +
( SELECT DeliveryQuantity FROM DeliveryContent WHERE StockID=sc.StockID )
WHERE StockID in (select StockID from DeliveryContent);
If more than one DeliveryContent can exist for each StockID, maybe DeliveryQuantity should be replaced by SUM(DeliveryQuantity).

Update row with value from next row sqlite

I have the following columns in a SQLite DB.
id,ts,origin,product,bid,ask,nextts
1,2016-10-18 20:20:54.733,SourceA,Dow,1.09812,1.0982,
2,2016-10-18 20:20:55.093,SourceB,Oil,7010.5,7011.5,
3,2016-10-18 20:20:55.149,SourceA,Dow,18159.0,18161.0,
How can I populate the 'next timestamp' column (nextts) with the next timestamp for the same product (ts), from the same source? I've been trying the following, but I can't seem to put a subquery in an UPDATE statement.
UPDATE TEST a SET nextts = (select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1);
If I call this, I can display it, but I haven't found a way of updating the value yet.
select a.*,
(select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1) as nextts
from TEST a
order by origin, a.id;
The problem is that you're using table alias for table in UPDATE statement, which is not allowed. You can skip alias from there and use unaliased (but table-name prefixed) reference to its columns (while keeping aliased references for the SELECT), like this:
UPDATE TEST
SET nextts = (
SELECT b.ts
FROM TEST b
WHERE b.id > TEST.id AND
TEST.origin = b.origin AND
TEST.product = b.product
ORDER BY b.id ASC
LIMIT 1
);
Prefixing unaliased column references with the table name is necessary for SQLite to identify that you're referencing to unaliased table. Otherwise the id column whould be understood as the id from the closest[*] possible data source, in which case it's the aliased table (as b alias), while we're interested in the unaliased table, therefore we need to explicitly tell SQLite that.
[*] Closest data source is the one listed in the same query, or parent query, or parent's parent query, etc. SQLite is looking for the first data source (going from inner part to the outside) in the query hierarchy that defines this column.

SQLITE fill value with unique random table

I want to create a table with a field that is unique and limited to a certain value. Lets say that the limit is 100, the table is full, I remove a random row, and when I create a new row it has the value that was freed before.
It doesn't need to be the fastest thing in the world (the limit is quite small), I just want to implement it in a DB.
Any ideas?
Create one more column in main table, say deleted (integer, 0 or 1). When you need to delete with certain id, do not really delete it, but simply update deleted to 1:
UPDATE mytable SET deleted=1 WHERE id = <id_to_delete>
When you need to insert, find id to be reused:
SELECT id FROM mytable WHERE deleted LIMIT 1
If this query returns empty result, then use INSERT to create new id. Otherwise, simply update your row:
UPDATE mytable SET deleted=0, name='blah', ... WHERE id=<id_to_reuse>
All queries reading from your main table should have WHERE constraint with NOT deleted condition:
SELECT * FROM mytable WHERE NOT deleted
If you add index on deleted, this method should work fast even for large number of rows.
This solution does everything in a trigger, so you can just use a normal INSERT.
For the table itself, we use an autoincrementing ID column:
CREATE TABLE MyTable(ID INTEGER PRIMARY KEY, Name);
We need another table to store an ID temporarily:
CREATE TABLE moriturus(ID INTEGER PRIMARY KEY);
And the trigger:
CREATE TRIGGER MyTable_DeleteAndReorder
AFTER INSERT ON MyTable
FOR EACH ROW
WHEN (SELECT COUNT(*) FROM MyTable) > 100
BEGIN
-- first, select a random record to be deleted, and save its ID
DELETE FROM moriturus;
INSERT INTO moriturus
SELECT ID FROM MyTable
WHERE ID <> NEW.ID
ORDER BY random()
LIMIT 1;
-- then actually delete it
DELETE FROM MyTable
WHERE ID = (SELECT ID
FROM moriturus);
-- then change the just inserted record to have that ID
UPDATE MyTable
SET ID = (SELECT ID
FROM moriturus)
WHERE ID = NEW.ID;
END;

Sqlite Query replacing a column with a column from another table

I have 2 tables, one is indexing the other.
I am querying Table#1, and it has one column (string) that has an ID in it that corresponds to a unique row in Table#2. Im trying to write a query in Sqlite that allows me to retrieve the value from Table#2 if the column value in Table#1 is not an empty string.
Kinda like:
"SELECT TMake,TModel,TTrim,IYear,[%q] AS TPart1 FROM AppGuide WHERE TPart1 != ''"
But instead of retrieving the Index value (TPart1) Id like to get the string from Table#2.
Is this possible?
Any help is appreciated.
You could use a correlated subquery:
SELECT TMake,
TModel,
...,
(SELECT stringvalue
FROM Table2
WHERE Table2.ID = Table1.TPart1)
FROM Table1
WHERE Table1.TPart1 != ''
However, these are rather slow to execute, so you'd better use a join (this returns exactly the same result):
SELECT Table1.TMake,
Table1.TModel,
...,
Table2.stringvalue
FROM Table1 LEFT JOIN Table2 ON Table1.TPart1 = Table2.ID
WHERE Table1.TPart1 != ''
If you don't want to get records from Table1 that have no matching Table2 record, drop the LEFT.

Resources