How return details of updated row? - excel

I have database in MS Access 2016, and want to run update query thru Excel VBA - this works. After this I want to return details of updated row (values from two columns - ID, Col1). Now I have only number of affected rows. How to achive this?
My query:
UPDATE
(SELECT TOP 1 ID, Col1, Update_time, Update_user
FROM Table1
WHERE Update_user Is Null
ORDER BY Col2 DESC , ID) AS U_ROW
SET U_ROW.Update_time = Now(), U_ROW.Update_user = [username];
In Excel VBA I run it thru ADODB.Command:
With baseRecordsetCommand
.ActiveConnection = objectConnection
.CommandType = adCmdStoredProc
.CommandText = "qryTest"
.NamedParameters = True
.Parameters.Append .CreateParameter("#username", adVarChar, adParamInput, 255, LCase(Environ("Username")))
.Execute recordsAffected
End With

Usually these kind of ops goes into a stored procedure but in Ms Acces/Excel you have to use VBA. Easiest way is, to retrieve the Id you are about to update before you the update.
So this comes first: save it in a variable
SELECT TOP 1 ID
FROM Table1
WHERE Update_user Is Null
ORDER BY Col2 DESC , ID
And then
update Table1
SET Table1.Update_time = Now(), Table1.Update_user = #username where Id = #idFromFirstQuery;
followed by
select * from Table1 where Id = #idFromFirstQuery;
in this way you know what Id, row you are updating.
OR:
you can turn the now() also into a parameter and supply a timestamp as parameter.
like:
update (table selection )
set update_time = '2020-19-03 10:0=10:10', update_user = 'User1';
after update you can do something like:
Select *
from Table1
where update_user = 'User1' and update_time = '2020-19-03 10:0=10:10';
NOTE!! you are highly assuming the timestamp you are supplying + username is unique. I personally would not use this method.

Not sure on this, but if you have a unique id, you could do something like this. This was done in Access, so the connection would need to be set up, as i believe this is ok.
Function sqlret() As String
Dim c As ADODB.Connection
Dim s As String
Dim r As ADODB.Recordset
Dim l As Long
Set c = CurrentProject.Connection
c.Execute "insert into tblprojects(projecttitle) values ('code1')"
Set r = New ADODB.Recordset
r.Open "select ##identity", c, 1
l = r.Fields(0).Value
r.Close
r.Open "select * from tblprojects where [projectid]=" & l, c, 1
sqlret = r.GetString
End Function

Related

Power Query - How to pass blank Excel cell as NULL value?

I have SQL that looks like this, which works fine in SSMS:
DECLARE #pPart VARCHAR(100) = '00039',
#pColor VARCHAR(100) = '01816'
SET #pPart = ISNULL(#pPart,'-1')
SET #pColor = ISNULL(#pColor,'-1')
SELECT *
FROM myTable
WHERE (PartID IN (SELECT (#pPart)) OR #pPart = '-1')
AND (ColorID IN (SELECT (#pColor)) OR #pColor = '-1')
If I change either value (or both values) in the DECLARE from a value to NULL, the code returns the results I expect. I'm just not sure how to make this work within Power Query. If both cells are populated with values, the query works. If I delete the value from either cell, it's just returning a list of all the tables in my database (weird...).
I created a named range called "GetValues" that covers B2:B3 and looks like this:
Name
Value
Part
00039
Color
01816
In the Advanced Editor of Power Query, my query looks like this:
let
Source = Excel.CurrentWorkbook(){[Name="GetValues"]}[Content],
pPart = Source{1}[Column1],
pColor = Source{2}[Column1],
Query = "
DECLARE #pPart VARCHAR(100) = '"& pPart &"',
#pColor VARCHAR(100) = '"& pColor &"'
SET #pPart = ISNULL(#pPart,'-1')
SET #pColor = ISNULL(#pColor,'-1')
SELECT *
FROM myTable
WHERE (PartID IN (SELECT (#pPart)) OR #pPart = '-1')
AND (ColorID IN (SELECT (#pColor)) OR #pColor = '-1')
",
Target = Sql.Database("myServer", "myDatabase", [Query=Query])
in
Target
I tried changing my SET lines, which also works in SSMS if I change a value to '' or ' ' but still returns a list of all tables in my DB in Power Query. I'm trimming the strings in case the user put a space in the cells instead of leaving them blank:
IF LTRIM(RTRIM(#pPart)) = '' SET #pPart = '-1'
IF LTRIM(RTRIM(#pColor)) = '' SET #pColor = '-1'
So how do I pass a blank cell as NULL or at least as '' ?
EDIT: I also tried stripping my query down to the bare bones to see what parameters are being passed. This query successfully returns the value in B2.
let
Source = Excel.CurrentWorkbook(){[Name="GetValues"]}[Content],
pPart = Source{1}[Column1],
Query = "
DECLARE #pPart VARCHAR(100) = '"& pPart &"'
SELECT #pPart
",
Target = Sql.Database("myServer", "myDatabase", [Query=Query])
in
Target
Now I want to see what happens when I include the blank cell B3:
let
Source = Excel.CurrentWorkbook(){[Name="GetValues"]}[Content],
pPart = Source{1}[Column1],
pColor = Source{2}[Column1],
Query = "
DECLARE #pPart VARCHAR(100) = '"& pPart &"',
#pColor VARCHAR(100) = '"& pColor &"'
SELECT #pPart, #pColor
",
Target = Sql.Database("myServer", "myDatabase", [Query=Query])
in
Target
This query also returned a list of all the tables in my database.
I also tried changing
in
Target
to
in
pColor
and the query preview shows null in all lowercase, which makes me think it's indeed returning a null value. I just can't figure out how to make this work.
If the goal is to treat blank cell values as a wildcard then this will work: first remove the SET statements then use this sql:
SELECT *
FROM myTable
WHERE (PartID = #pPart OR #pPart is null OR TRIM(#pPart) ='')
AND (ColorID = #pColor OR #pColor is null OR TRIM(#pColor) ='')
You would get:
Alll rows only if both variables are blank.
No rows if #pPart is not null/blank and has no matches
No rows if #pColor is not null/blank and has no matches
You could add this condition to prevent returning any rows when both inputs are blank/ null:
AND ( ISNULL(TRIM(pPart), '') <> '' OR ISNULL(TRIM(pColor), '') <> '')
To get this to work, I had to address the null values before the query started. For whatever reason (EDIT: Jeroen gives the actual reason in the comment below), passing pPart or pColor as NULL would just return a list of tables and didn't actually pass the NULL value. Here's what seems to be working:
let
Source = Excel.CurrentWorkbook(){[Name="GetValues"]}[Content],
pPart = if Source{1}[Column1] = null then "-1" else Source{1}[Column1],
pColor = if Source{2}[Column1] = null then "-1" else Source{2}[Column1],
Query = "
DECLARE #pPart VARCHAR(100) = '"& pPart &"',
#pColor VARCHAR(100) = '"& pColor &"'
SELECT *
FROM myTable
WHERE (PartID= '" & pPart & "' OR " & pPart & " = '-1')
AND (ColorID = '" & pColor & "' OR " & pColor & " = '-1')
",
Target = Sql.Database("myServer", "myDatabase", [Query=Query])
in
Target

SQL Server : MERGE statement, compare with select data instead of table data

merge into item_set TARGET
using (select '545934' as product_id_01, 4 as set_sort_no, 15 as article_id,
'Note for this item set' as note, 0 as is_deleted) as SOURCE
on TARGET.set_sort_no = SOURCE.set_sort_no and TARGET.product_id_01 = SOURCE.product_id_01
WHEN MATCHED THEN
UPDATE
SET TARGET.article_id = SOURCE.article_id,
TARGET.note = SOURCE.note,
TARGET.is_deleted = SOURCE.is_deleted,
TARGET.version = TARGET.version
WHEN NOT MATCHED THEN
INSERT (product_id_01, set_sort_no, article_id, note, is_deleted, version)
VALUES (SOURCE.product_id_01, SOURCE.set_sort_no, SOURCE.article_id, SOURCE.note, SOURCE.is_deleted, 3);
I have a query as shown above, I would like to know if it is possible to use multiple values(array of values) instead of the below statement from the query without using a table
(select
'545934' as product_id_01,
4 as set_sort_no, 15 as article_id,
'Note for this item set' as note, 0 as is_deleted) as SOURCE
Thanks in advance.
No.MS SQL Server was not designed to support arrays

Merge in Spark SQL - WHEN NOT MATCHED BY SOURCE THEN

I am coding Python and Spark SQL in Databricks and I am using spark 2.4.5.
I have two tables.
Create table IF NOT EXISTS db_xsi_ed_faits_shahgholi_ardalan.Destination
(
id Int,
Name string,
Deleted int
) USING Delta;
Create table IF NOT EXISTS db_xsi_ed_faits_shahgholi_ardalan.Source
(
id Int,
Name string,
Deleted int
) USING Delta;
I need to ran a Merge command between my source and destination. I wrote below command
%sql
MERGE INTO db_xsi_ed_faits_shahgholi_ardalan.Destination AS D
USING db_xsi_ed_faits_shahgholi_ardalan.Source AS S
ON (S.id = D.id)
-- UPDATE
WHEN MATCHED AND S.Name <> D.Name THEN
UPDATE SET
D.Name = S.Name
-- INSERT
WHEN NOT MATCHED THEN
INSERT (id, Name, Deleted)
VALUES (S.id, S.Name, S.Deleted)
-- DELETE
WHEN NOT MATCHED BY SOURCE THEN
UPDATE SET
D.Deleted = 1
When i ran this command i have below error:
It seems that we do not have NOT MATCHED BY SOURCE in spark! I need a solution to do that.
I wrote this code but still i am looking for better approach
%sql
MERGE INTO db_xsi_ed_faits_shahgholi_ardalan.Destination AS D
USING db_xsi_ed_faits_shahgholi_ardalan.Source AS S
ON (S.id = D.id)
-- UPDATE
WHEN MATCHED AND S.Name <> D.Name THEN
UPDATE SET
D.Name = S.Name
-- INSERT
WHEN NOT MATCHED THEN
INSERT (id, Name, Deleted)
VALUES (S.id, S.Name, S.Deleted)
;
%sql
-- Logical delete
UPDATE db_xsi_ed_faits_shahgholi_ardalan.Destination
SET Deleted = 1
WHERE db_xsi_ed_faits_shahgholi_ardalan.Destination.id in
(
SELECT
D.id
FROM db_xsi_ed_faits_shahgholi_ardalan.Destination AS D
LEFT JOIN db_xsi_ed_faits_shahgholi_ardalan.Source AS S ON (S.id = D.id)
WHERE S.id is null
)

How to create update query with QSqlQuery

I'm trying to create an update query in Python3/PyQt5.10/Sqlite . A select/insert query made the same way runs fine. Fields & corresponding record exist.
def updateRecords():
theDict = {
"Loc": "PyQt121",
"BoekNr" : "dfdf",
"BoekTitel" : "eeee",
"BoekBedrag" : 999
}
theFilter = " WHERE Loc = 'PyQt'"
query = QSqlQuery()
columns = ', '.join(pDict.keys())
placeholders = ':'+', :'.join(pDict.keys())
sql = 'UPDATE %s SET (%s) VALUES (%s) %s' % (pTable, columns, placeholders, pFilter)
query.prepare(sql)
for key, value in pDict.items():
query.bindValue(":"+key, value)
print (sql)
query.exec_()
print(query.lastError().databaseText())
return query.numRowsAffected()
The sql generated is UPDATE tempbooks SET (Loc, BoekNr, BoekTitel, BoekBedrag) VALUES (:Loc, :BoekNr, :BoekTitel, :BoekBedrag) WHERE Loc = 'PyQt'.
query.lastError().databaseText()) give me "No Query" and updated rows is -1.
The correct syntax for an update query:
UPDATE tablename
set col1 = val1,
col2 = val2,
col3 = val3
WHERE condition
Probably query.prepare(sql) is returning False because of invalid syntax.

Autoincrement SQL server 2008/c#

How do I increment field of table using varchar. Here an example of what I want to have:
Mark 00001
Mark 00002
Mark 00003
Jaques 00001
Jaques 00002
Jaques 00003
Here is my example It can be useful for other people thanks to those who have helped me a lot thank you
The table is
`CREATE TABLE [dbo].[TAG_Sinistre](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ref_ag] [varchar](7) NULL,
[ref_sinistre] [varchar](7) NULL,
)`
The stored procedure is
create PROC [dbo].[sp_Add_AgSinistre]
#ref_ag varchar (7)
AS BEGIN
declare #id int
DECLARE #ref_sin VARCHAR
SET #id = (SELECT ISNULL(MAX(CAST(ID AS INT)), 0) + 1
FROM TAG_Sinistre where ref_ag=#ref_ag
)
select #ref_sin=right('000000'+CAST(#ref_sin AS VARCHAR(6)),6)
BEGIN
INSERT into TAG_Sinistre(ref_ag,ref_sinistre)
VALUES (#ref_ag,#ref_sin)
Assuming the CompanyName field is UNIQUE, you could get the MAX added value, and increment that?
DECLARE #CurrentSequence INT
SET #CurrentSequence = (SELECT MAX(SequenceId)
FROM TableName WHERE CompanyName = #CompanyName)
INSERT INTO TableName
(CompanyName, SequenceId)
VALUES
(#CompanyName, #CurrentSequence+1)
Your StoredProc would pass in the Company Name as #CompanyName. Obviously, this is a naive approach, and I'm not including what would happen if multiple attempts to update the company would happen simultaneously, but there's no mention of that ion the question.
EDIT: Based on comments
DECLARE #maxSeq INT
SET #maxSeq = (SELECT ISNULL(MAX(CAST(SequenceId AS INT)), 0) + 1 FROM
TableName WHERE CompanyName = #CompanyName)
INSERT INTO TableName
(CompanyName, SequenceId)
VALUES
(#CompanyName, right('000000'+CAST(#maxSeq AS VARCHAR(7)),7))
As I said, I would look to use an INT, and get the UI to present the sequence as you want, instead of casting etc in the DB.
EDIT 2: Added Fiddle
SQL Fiddle
Assuming that your columns always look like those specified above.
DB Trigger (MS-SQL) --> Pseudocode/Untested:
CREATE TRIGGER [dbo].[YourTrigger]
ON [dbo].[YourTable]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #maxVal int
-- PSEUDOCODE!!!
SELECT #maxVal = MAX(CAST(dbo.RegexReplace( '.*?(\d+)', myColumn, '$1') AS INT ))
FROM YourTable
INSERT INTO YourTable
SELECT myColumn + ' ' + #maxVal FROM inserted
END
Use insert now like this:
INSERT INTO YourTable values('Jaques')

Resources