Get inserted uniqueidentifier from table B when its inserted from Table A insert trigger - database-trigger

I wasnt sure how to open the title but let me explain what is my problem.
I have two tables and both of them used uniqueidentifier as Id and they are auto generated by newsequentialid()
Now, when i make an insert to table B, it runes Insert trigger and i do some specific things inside this trigger and i also insert some values to another table called A and i need to retreive this table A's inserted Id but i am unable to find a solution.
Also let me explain why i need such a trigger. When a user creates an invoice with products in it where they have stock information, this trigger is responsible to create a stock transaction with header and detail about the products inserted (this stock detail table also has a trigger and it updates the warehouses) etc. etc.
i hope this gives some hint what i am trying to do
CREATE TRIGGER [dbo].[IT_TBLDebitInvoiceDetails] ON [dbo].[TBLDebitInvoiceDetails] AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare #cnt int;
--HEADER
declare #DocumentId uniqueidentifier;
declare #OrganizationId uniqueidentifier;
declare #Date date;
declare #TermDate date;
declare #DespatchDate date;
declare #DespatchNo nvarchar(20);
declare #WarehouseId uniqueidentifier;
declare #CustomerId uniqueidentifier;
declare #StockId uniqueidentifier;
declare #CurrencyTypeId uniqueidentifier;
declare #GrandTotal money;
--Auditable
declare #WhoCreated uniqueidentifier;
declare #DateCreated datetime;
declare #WhoUpdated uniqueidentifier;
declare #DateUpdated datetime;
--DETAIL
declare #ProductId uniqueidentifier;
declare #Quantity decimal(18, 2);
declare #ProductType int;
SELECT TOP(1) #OrganizationId = OrganizationId, #DocumentId = A.Id, #Date = A.[Date], #TermDate = A.TermDate, #DespatchDate = A.DespatchDate, #DespatchNo = A.DespatchNo,
#WarehouseId = A.WarehouseId, #CustomerId = A.CustomerId, #GrandTotal = A.GrandTotal,
#WhoCreated = A.WhoCreated, #DateCreated = A.DateCreated, #WhoUpdated = A.WhoUpdated, #DateUpdated = A.DateUpdated
FROM TBLDebitInvoices AS A
INNER JOIN inserted AS B ON A.Id = B.InvoiceId
/* CHECK STOCK TRANSACTION */
SELECT #cnt = COUNT(*) FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
WHERE B.ProductType != 1
--we have products for stock, create stock header
IF(#cnt > 0)
BEGIN
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
VALUES (#OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0);
SELECT #StockId = ???????;
END
INSERT INTO TBLStockDetails (StockId, ProductId, [Value])
SELECT #StockId, ProductId, SUM(Quantity) FROM (
SELECT A.ProductId AS ProductId, A.Quantity FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
WHERE B.ProductType = 0
UNION ALL
SELECT C.IngredientID, A.Quantity * C.Quantity FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
INNER JOIN TBLProductRecipes AS C ON C.ProductId = B.Id
WHERE B.ProductType = 2
) AS T1
GROUP BY ProductId;
UPDATE TBLDebitInvoices SET StockId = #StockId WHERE Id = #DocumentId;
/* CHECK DC TRANSACTION */
INSERT INTO TBLDebitCreditTransactions (TransactionType, DocumentType, DocumentId, PaymentStatus, [Date], Amount, AccountType, AccountId, CurrencyTypeId)
VALUES (1, 0, #DocumentId, 0, #TermDate, #GrandTotal, 0, #CustomerId, #CurrencyTypeId);
END
GO
inside this trigger i have this insert:
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
VALUES (#OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0);
SELECT #StockId = ???????;
and i need the Id inserted to this table so i can use its id to insert its row elements.

it seems i found the answer, i wasnt sure inserted statement will give a separate result for the second insert, but it works
DECLARE #IdTable TABLE (StockId uniqueidentifier);
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
OUTPUT Inserted.Id INTO #IdTable(StockId)
SELECT #OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0;
SELECT #StockId = StockId FROM #IdTable;
this will give the second table inserted uniqueidentifier

Related

How to use string as column name in Bigquery

There is a scenario where I receive a string to the bigquery function and need to use it as a column name.
here is the function
CREATE OR REPLACE FUNCTION METADATA.GET_VALUE(column STRING, row_number int64) AS (
(SELECT column from WORK.temp WHERE rownumber = row_number)
);
When I call this function as select METADATA.GET_VALUE("TXCAMP10",149); I get the value as TXCAMP10 so we can say that it is processed as SELECT "TXCAMP10" from WORK.temp WHERE rownumber = 149 but I need it as SELECT TXCAMP10 from WORK.temp WHERE rownumber = 149 which will return some value from temp table lets suppose the value as A
so ultimately I need value A instead of column name i.e. TXCAMP10.
I tried using execute immediate like execute immediate("SELECT" || column || "from WORK.temp WHERE rownumber =" ||row_number) from this stack overflow post to resolve this issue but turns out I can't use it in a function.
How do I achieve required result?
I don't think you can achieve this result with the help of UDF in standard SQL in BigQuery.
But it is possible to do this with stored procedures in BigQuery and EXECUTE IMMEDIATE statement. Consider this code, which simulates the situation you have:
create or replace table d1.temp(
c1 int64,
c2 int64
);
insert into d1.temp values (1, 1), (2, 2);
create or replace procedure d1.GET_VALUE(column STRING, row_number int64, out result int64)
BEGIN
EXECUTE IMMEDIATE 'SELECT ' || column || ' from d1.temp where c2 = ?' into result using row_number;
END;
BEGIN
DECLARE result_c1 INT64;
call d1.GET_VALUE("c1", 1, result_c1);
select result_c1;
END;
After some research and trial-error methods, I used this workaround to solve this issue. It may not be the best solution when you have too many columns but it surely works.
CREATE OR REPLACE FUNCTION METADATA.GET_VALUE(column STRING, row_number int64) AS (
(SELECT case
when column_name = 'a' then a
when column_name = 'b' then b
when column_name = 'c' then c
when column_name = 'd' then d
when column_name = 'e' then e
end from WORK.temp WHERE rownumber = row_number)
);
And this gives the required results.
Point to note: the number of columns you use in the case statement should be of the same datatype else it won't work

Trigger to insert new quote number in this format

I am very new at triggers - actually this will be my first one.
What I am trying to achieve is the following:
When I create a new Sales Opportunity, the Quote no field needs to spit out a number starting from this Q1500/09/2017 so Q is the prefix, 1500 is the first quote number, 09 the month and 2017 the year.
Can someone assist me in getting this right - do i need a SP and a table in order for my trigger to work correctly?
Quote_No is a table field so I'm guessing it should look something like this:
CREATE TABLE [dbo].[Quote_Pref_No](
[Yr] [varchar](4) NULL,
[Mth] [varchar](2) NULL,
[Quote_Pref] [varchar](10) NULL,
[Quote_No] [int] NULL
) ON [PRIMARY]
Then the SP:
Create Proc [dbo].[New_Quote_Num] #ClientID varchar(24),#ContactNum int, #Year varchar(4), #mth varchar(2)
As
Begin
Declare #Pref varchar(5),
#Num int,
#QuoteNo varchar(255)
Select #QuoteNo = B.Description
From dbo.AMGR_User_Fields_Tbl A inner join dbo.AMGR_User_Field_Defs_Tbl B
on A.Type_Id = B.Type_Id and A.Code_Id = B.Code_Id and A.Type_Id = 117
Where A.Client_Id = #ClientId and A.Contact_Number = #ContactNum
Select #Pref = Quote_Pref, #Num = Quote_No + 1
From dbo.Quote_Pref_No
Where Yr = #Year and Mth = #Mth
Set #QuoteNum = 'Q/'+Right(#Year,2)+'/'+Right(#mth,2)+'/'+#Pref+case when Len(#Num) <= 3 then Right('000000'+Convert(Varchar(55),#Num),3) else CONVERT(Varchar(55),#Num) end
Insert into dbo.O_QuoteNo(Client_Id,Contact_Number,Type_Id,Code_Id,O_QuoteNo)
Values(#ClientId,#ContactNum,13,0,#QuoteNum)
Update dbo.Quote_Pref_No
Set Quote_No = #Num
Where Yr = #Year and mth = #mth
End
Grant execute on dbo.New_Quote_Num to CRMGroup
GO
I just dont know how to generate the month and year together.
Trigger code:
Create Trigger [dbo].[QuoteNew]
on [dbo].[AMGR_User_Fields_Tbl] after insert
As
Declare #ClientId varchar(24),
#ContactNum int,
#TypeId int,
#Year varchar(4),
#quoteYear varchar(4),
#mth varchar(2)
Select #ClientId = Client_Id,
#ContactNum = Contact_Number,
#TypeId = TYPE_ID,
#Year = CONVERT(varchar(4),Datepart(yyyy,DateCol)) from inserted
#mth = convert(varchar(2), datepart(mm,Datecol)) from inserted
Select #quoteYear = Yr from dbo.quote_Pref_No where Yr = #Year
select #mth = mth from dbo.quote_Pref_No where mth = #mth
If #TypeID = 117 and #QuoteYear is null or #quoteYear = ''
Begin
Execute dbo.New_Year_Certs #Year
Execute dbo.New_quote_Num #ClientId,#ContactNum,#Year
End
If #TypeID = 117 and #quoteYear = #Year
Begin
Execute dbo.New_Cert_Num #ClientId,#ContactNum,#Year
End
GO
Do I need to create a separate SP for month or can I do both month and year in one SP?

How to use date() function / return hydrated objects?

In my Entity Repository for Doctrine2, I have the following:
$date = new DateTime('NOW');
$date = $date->format('Y-m-d');
if ($region) {
$region_sql = " AND WHERE region LIKE ?3 ";
} else {
$region_sql = "";
}
$sql = "SELECT *, count(month) as count FROM (SELECT *, date(date_from, 'start of month', '+1 month', '-1 day') as month FROM manifestations WHERE date_to >= :date_to " . $region_sql . ") GROUP BY month";
$stmt = $em->getConnection()->prepare($sql);
$stmt->bindValue(':date_to', $date);
if($region) {
$stmt->bindValue(3, sprintf('%%,%s,%%', $region));
}
$stmt->execute();
return $stmt->fetchAll();
But I need to change this so that it returns the objects hydrated instead of an array. I originally wanted to use DQL or queryBuilder but could not find a way to get the date() function to work.
With NativeQuery you can execute native SELECT SQL statements and map the results to Doctrine entities or any other result format supported by Doctrine.
What you want to do can be achieved using the ResultSetMappingBuilder.
ResultSetMappingBuilder is a convenience wrapper. It can generate the mappings for you based on Entities.
This is how I'd do it (I assume your query works, maybe you'll have to adjust it, as I will use a new alias):
Create the ResultSetMapping:
use Doctrine\ORM\Query\ResultSetMapping;// Don't forget this
$rsm = new ResultSetMappingBuilder($entityManager);// $entityManager points to your entity manager.
$rsm->addRootEntityFromClassMetadata('path/to/class/MyClass', 'a');// Notice the a, it's an alias that I'll later on use in the query.
$rsm->addScalarResult("count", "count");// column, alias
Prepare $region_sql part as you do in your code and add the a alias to whatever you want to map. a.* will be mapped to an object (notice the as a I use in the query):
$sql = "SELECT a.*, count(month) as count FROM (SELECT *, date(date_from, 'start of month', '+1 month', '-1 day') as month FROM manifestations WHERE date_to >= :date_to " . $region_sql . ") as a GROUP BY month";
Execute the query:
$query = $entityManager->createNativeQuery($sql, $rsm);
$query->setParameter('date_to', $date);
$result = $query->getResult();
This will give you an array of rows. Each of them will be a mixed array, $result[n][0] will contain the object and $result[n]["count"] the value of the count column of the query (name of the column is the same as the alias we set up in the $rsm) where n is the number of the row.

CDaoRecordSet select all from column

How can i store all the records of a column in a CDaoRecordSet? I've tried this, but will only return the first record of that column:
rs.Open(dbOpenSnapshot, "SELECT Numar_inmatriculare FROM Masini");
short nFields = rs.GetFieldCount();//returns 1
If i make a "SELECT count(*) AS Numar_inmatriculare FROM Masini" and use rs.GetFieldValue(0) it returns me 13, the correct number of records.
GetFieldCount returns the number of columns in your resultset.
To iterate through the records (=rows), you have to call MoveNext until IsEOF() returns true.
rs.Open(dbOpenSnapshot, "SELECT Numar_inmatriculare FROM Masini");
while(!rs.IsEOF())
{
// do something
rs.MoveNext();
}

Select the record of a given id with the highest timestamp using DAO

How do I do the following using DAO on a recordset
SELECT TOP 1 * FROM foo WHERE id = 10 ORDER BY timestamp DESC
Using SetCurrentIndex you can only use one index it seems otherwise using id and timestamp and selecting the first one would work.
I am by no means sure of what you want.
Dim rs As DAO.Recordset
Dim db As Database
Set db = CurrentDB
sSQL = "SELECT TOP 1 * FROM foo WHERE id = 10 ORDER BY timestamp DESC"
Set rs = db.OpenRecordset(sSQL)
Find does not work with all recordsets. This will work:
Set rs = CurrentDb.OpenRecordset("select * from table1")
rs.FindFirst "akey=1 and atext='b'"
If Not rs.EOF Then Debug.Print rs!AKey
This will not:
Set rs = CurrentDb.OpenRecordset("table1")
rs.FindFirst "akey=1 and atext='b'"