TableAdapter.insert - Get ID (With SCOPE_IDENTITY)? (SQL Server) - vb.net

I can't figure out how to get the ID of the record created with tableadapter.insert() command.
I read several answers to similar questions but most of them shift to how to do it with COMMANDS and ADO or with Stored Procedures.
The closest I found was the recommendation to add SELECT SCOPE_IDENTITY() to the end of the INSERT statement.
https://www.screencast.com/t/BU3F73ds
INSERT INTO [zGrid Filters and Layouts]
(XML, UserID, Type, Global, LastModDt, SaveName)
VALUES (#XML,#UserID,#Type,#Global,#LastModDt,#SaveName);
SELECT SCOPE_IDENTITY()
But when I do that, I get a "can't parse" error when I click Finish.
https://www.screencast.com/t/7R5MN3cF
Then I also set the Execute to Scalar.
https://www.screencast.com/t/w91RECeLUL2
And if I bypass that error, I get a runtime error saying I need to declare the scalar value.
https://www.screencast.com/t/RbNuizo65vu
I've verified my INSERT (SQL) code. In fact, I've confirmed it does insert without the SELECT SCOPE_IDENTITY line.
Dim ID As Int32 =
DataTableGridFiltersLayoutsTableAdapter1.InsertRecord(xmlString,
1, "F", 1, Now, "My New Block 3")
I included the results, above.
To clarify, I want to figure this out using the generated table adapter -- unless the answer is you can't do it with table adapters (which doesn't seem right).
I've found countless articles that say it's possible but none of them actually show you how to do it -- beyond the tableadapter.insert line.
Any help is appreciated.

Related

Why is a query under a IF statement that is false running?

I have a application that uses a lot of string interpolation for SQL queries. I know it is a SQL injection threat, this is something that the customer and us know about and is hopefully something we can focus on next big refactor. I say that to make sense of the {Root Container.property} things that come from a GUI.
I have this query
IF ({Root Container.UserSelectedProduct}=1)
begin
DECLARE #TestNumbers {Root Container.SQLProductType};
INSERT INTO #TestNumbers SELECT * FROM {Root Container.DBTable};
SELECT *
FROM {Root Container.SQLProductFunction} (#TestNumbers)
WHERE [ID] = {Root Container.Level};
end
else
Select 0
Before a user selects a product it looks like this
IF (0=1)     
BEGIN
DECLARE #TestNumbers myDataType;
INSERT INTO #TestNumbers SELECT * FROM [MySchema].[TheWrongTable];     
SELECT * FROM [dbo].[myfunction] (#TestNumbers)
WHERE [ID] = 1;
END
ELSE
SELECT 0
Which is giving me the error:
Column name or number of supplied values does not match table definition.
I am aware why this error shows up, the table I am selecting from is not made for that data type.
However, why is it even attempting to run the first IF clause when I have IF (0=1) - how come this part is not just skipped and the SELECT 0 is only run? I would have thought that is how it was supposed to work, but I keep getting the error regarding column name/number not matching the table definition. When the user does select a Product and I get IF (1=1) and I have the appropriate table/function/datatype, it all works smoothly. I just don't know why it throws me an error prior when IF(1=0). Why does this happen/how can I get my intended behavior that everything inside my BEGIN\END under my first IF statement does not run unless the expression is true.
T-SQL is not interpreted. It must make sense regardless of what the runtime conditions are. It doesn't even do short-circuiting, in fact. Your code is invalid, and it doesn't matter that it's unreachable - T-SQL isn't going to ignore a piece of invalid code just because it could be eliminated, that's a thing that is a common source of bugs (e.g. in C++ where it's pretty common with templates).
Just make sure you still get valid SQL for the case where no product is selected; use the wrong table (or a helper table) if you have to.
The answer is simple: SQL code is fully compiled by the server before being executed, so this is basically a compile error. It's a bit like trying to compile the following in C#
if(someBoolWhichIsFalse)
intValue = "hello";
It's simply not valid.
The runtime code has not even been executed, it's still in the parsing and lexing stage. Nothing is being skipped, it just needs to be fully valid code, irrespective of runtime conditions.
This happens in every scope, i.e. on every call to a procedure or ad-hoc batch, that code must be compilable.

Getting results from Oracle stored procedure insertion through pyodbc

I am using pyodbc (version 3.0.7) to access an Oracle (version 11g) database. We are writing stored procedures to handle the insertions. The primary keys for inserted objects are assigned with triggers, so we want to get the newly-inserted object's primary key into python after the stored procedure is called by the python script. (Due to client requirements, we don't have the flexibility of changing database, libraries, etc.)
According to the pyodbc documentation, return (OUT) parameters in stored procedures are not supported. Neither are stored functions. The documentation suggests to add a SELECT statement to the end of a stored procedure to get results out. However, we are new to SQL scripting, and Google searching for the last two days has turned up a lot of information for SQLServer and other databases, but next to nothing for Oracle. Trying the SQLServer examples on the Oracle db has not been tremendously helpful, as the Oracle SQL Developer shows various errors with the syntax (DECLARE where one shouldn't be, INTO required for SELECT statements, etc.).
Ultimately, we want the stored procedure to insert a new object, and then we want to somehow get the newly-created primary key for that object.
Here is an example of a stored procedure that correctly inserts an object (note that if obj_id is given as "None" in python, then the object is assigned a new primary key by a trigger):
CREATE OR REPLACE PROCEDURE insert_an_obj (an_obj_id NUMBER) AS
new_primary_key NUMBER;
BEGIN
INSERT INTO OBJS (OBJ_ID) VALUES (an_obj_id) RETURNING OBJ_ID INTO new_primary_key;
-- A SELECT statement should go here in order to get the new value for new_primary_key.
END insert_an_obj;
Supposedly, a SELECT statement at the end of the stored procedure will make it so the next time my script calls cursor.fetchall(), the script would get a list of whatever was selected. However, I have been unable to get this to work. Some failed SELECT examples (one of which might go in the stored procedure above in place of the SELECT comment) include the following:
-- These fail to compile because SQL Developer doesn't like them (though various sources online said that they work on SQLServer):
SELECT * FROM OBJS WHERE OBJ_ID=new_primary_key;
SELECT OBJ_ID FROM OBJS WHERE OBJ_ID=new_primary_key;
Like I said, I'm new to SQL, and likely I just need to know the proper syntax to get the SELECT statement working nicely in Oracle. Any suggestions? Or is there something that I'm misunderstanding?
As mentioned by Justin Cave in the comment above, "you can't just put a SELECT in a stored procedure to return data to the client." At least not with Oracle 11g. He continues: "In 11g, the only way to regurn data from a stored procedure is to have an OUT parameter", which AFIK, not possible using version 3.0.7 of pyodbc.

SQL Server Insert Into Select one row at a time

I am trying to use
INSERT INTO [table]
SELECT [columns]
FROM [table2]
WHERE [clause]
It loads perfectly. There is an error on row (?) so the entire insert is rolled back. I am trying to get this to load before and after the error. Also found TRY...CATCH in SQL to handle these issues.
Now, CURSOR seems like the exact answer but everything I read states that CURSOR should be avoided and is not Best Practice.
Anyone have a better option for my exact situation.

SQL Server multi-part identifier '%1' could not be bound with INSERTED pseudo-table

The situation : I'm writing an AFTER INSERT trigger on a table, so I can access to INSERTED pseudo-table, if I have good memory. The trigger is a bit long, so I can't copy / pasta it here, but basically, I'd like to compare the datas of the row I'm inserting (representing a good) with the rows of another table (very similar, representing the wishes), in order to determine if the good inserted corresponds to someone's wishes.
So, I almost finished my trigger, but an error occurred. At a given point, I wrote :
-- Create and open a cursor
IF (#variable1 = INSERTED.MyField)
BEGIN
-- some code
END
-- Deallocate and close my cursor
But I have the following error :
The multi-part identifier "INSERTED.MyField" could not be bound
I thought I could do it, as there is only one line in INSERTED as this moment (I'm right, don't I ?), but it seems I can't.
Can someone explain me why I'm wrong ?
PS : Yes, I've seen this link, or this one, or this one, but they all have a problem with JOIN, and I don't have any JOIN in here
That error indicates SQL is trying to read 'INSERTED' as an alias for another table
IF (#variable1 = INSERTED.MyField)
Try the following to reference the inserted table
IF (#variable1 = MyField from inserted)
Using the inserted and deleted Tables:
http://technet.microsoft.com/en-us/library/ms191300%28v=sql.105%29.aspx
This fixes the syntax and answers the question of why the error is occurring, but comparing inserted to a scalar variable is not recommended. As HLGEM stated, what if you have multiple values in the insert where some match and some don't.
Additionally, Cursors should be a last resort in SQL. In general, cursors are slower and hold up resources. SQL is a optimized for set-based operations and cursors don't leverage that. Without knowing exactly what you are trying to do in the cursor and how much data you are manipulating, I can't say definitely in this case.
One of the many discussions on StackOverflow about Cursors: stackoverflow.com/questions/743183/what-is-wrong-with-cursors

SQL Try Catch the exact errors caused by the recent variables

Query:
BEGIN TRY
SELECT #AccountNumber,
#AccountSuffix,
#Sedat,
#Dedo,
#Payalo,
#Artisto
FROM SWORDBROS
WHERE AMAZING ='HAPPENS'
END TRY
EGIN CATCH
Print #Sedat
END CATCH
How can I get the #Sedat, is it possible?
SQL 2005 , it will be in an SP
Like this, no?
BEGIN TRY
SELECT #AccountNumber,
#AccountSuffix,
#Sedat,
#Dedo,
#Payalo,
#Artisto
FROM SWORDBROS
WHERE AMAZING ='HAPPENS'
END TRY
BEGIN CATCH
--error handling only
END CATCH
--There is no finally block like .net
Print #Sedat
IN a proc when I want to trap the exact values that caused an erorr, this is what I do. I declare a table variable (very important must be a table variable not a temp table) that has the fields I want to have information on. I populate the table variable with records as I go. In a multitep proc, I would add one record for each step if I wanted to see the who process or only a record if I hit an error (which I would populate in this case in the catch block typically). Then in The catch block I would rollback the transaction and then I would insert the contents of the table varaible into a permanent exception processing table. You could also just do a select of this table if you wanted, but if I'm going to this much trouble it usually is for an automated process where I need to be able to research the problem at a later time, not see the problem when it hits becasue I'm not running it on my mchine or where I could see a select or print statement. By using the table varaible which stay in scope even after the rollback, my information is still available for me to log in my exception logging table. But it important that you do the logging to any permananent table after the rollback or the process will rollback with everything else.
which database are you using?
also, which programming language is this?
usually there would be an INTO clause and some local variables declared.
your query should also have a FROM clause at a minimum
It is not clear if you are expecting the returned values to be placed into the # variables or whether you are trying to dynamically specify which columns you want selected. In a Sql Server stored procedure you usually return a result set, not a bunch of individual variables. The syntax you have will not work if you want column values returned since what you have will dynamically specify which columns are wanted based on the column names passed into the stored procedure. And this will not work since the stored procedure must know which columns you are going after when it is analyzed as it is stored. Now the except clause will be trigged if there is a problem reading from the database (communication down, disk error, etc.) in which case none of the column values will be known.
Use the Sql Query Analyzer tool (under the "Tools" menu in SqlManager after you have selected a database) to define your stored procedure and test it. If you installed the documentation when you installed SqlManager go to Start>Programs>Microsoft Sql Server>Books Online and open the "Transact-SQL Reference" node for documentation on what can be done.