Strange result with - sqlite

When i run this as my first commend i get an exception an error near "last_insert_rowid". This is referring to the last last_insert_rowid();. If i set the curser to the line command.CommandText = and run it again it is fine.
What gives? The last_insert_rowid seems to be working properly why doesnt the last_insert_rowid after the 2nd insert work.
I tried moving last_insert_rowid() to after the execute and i still get an error. What gives?
using (var trans = connection.BeginTransaction())
{
command.CommandText =
"INSERT INTO link_list(link, status, hash_type, hash_id) " +
"VALUES(#link, #status, #hash_type, #hash_id);" +
"INSERT INTO active_dl(linkId, orderNo) " +
"VALUES(last_insert_rowid(), (SELECT COUNT(*) FROM active_dl)); last_insert_rowid();";
command.Parameters.Add("#link", System.Data.DbType.String).Value = link;
command.Parameters.Add("#status", System.Data.DbType.Int32).Value = SiteBase.Status.none;
command.Parameters.Add("#hash_type", System.Data.DbType.Int32).Value = 0;
command.Parameters.Add("#hash_id", System.Data.DbType.Int32).Value = 0;
int rowid = command.ExecuteNonQuery();
trans.Commit();
}

Why is the last last_insert_rowid() there? After the second insert you call last_insert_rowid with no select or anything to identify what you want to do with it.
You would have to put a select in front of it to retrieve the value wouldn't you?

You're trying to execute 2 sql commands in the one statement. You'll need to split the 2 statements up into 2 calls and return the inserted id from the first statement.
An alternative suggestion is a stored procedure but I don't think sqlite supports these.

Related

Can I use CASE WHEN outside of SELECT in SQLite/Conditional Structure in SQLite?

In SQL Server, I can use IF conditional structure to execute some statements if a condition is true. According to this and this, there seem to be no such structure in SQLite.
I want to check if a table exist, if it does, do nothing, if not, do a lot of things including creating tables, inserting and deleting data from other tables and updating as well:
CASE WHEN ((SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'TraitsSwap') = 1) THEN
-- 50 lines of code, including CREATE, DROP, INSERT, DELETE and UPDATE statements, with random() in used
ELSE
-- Do nothing
END
Is there anyway I can achieve this? The code includes usage of random() and it requires consistent result (i.e, only random in the first time). I am sorry if this sounds unreasonable, but this is in context of game modding, so I cannot really change the backend code to run separated transaction code.
I think there may be an alternative if there is a function in SQLite that can execute a string/statement block and return a result. For that, I can transform the query into
SELECT CASE WHEN ((SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'TraitsSwap') = 1) THEN
ExecuteCode("Code; RETURN 1;")
ELSE
0
END
I tried
SELECT CASE WHEN ((SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'TraitsSwap') = 1) THEN
SELECT 1;
INSERT INTO Foo(Test) VALUES("");
SELECT "A";
ELSE
SELECT 1;
SELECT 2;
SELECT "A";
END
but it's unsuccessful, the error is
near "SELECT": syntax error: SELECT CASE WHEN ((SELECT COUNT(*) FROM
sqlite_master WHERE type = 'table' AND name = 'TraitsSwap') = 1) THEN
SELECT

Teradata Insert Count into Variable

Description what I am trying to do:
I have 2 environments one has data (X) second one has no data (Y).
I have done procedure which has input parameter P_TableName. It should check if in this table is any data and IF There is then we will take data to Y environment.
So Mostly it works but I have problem with one freaking simple thing ( I have not much experience in TD but in Oracle it would be a 10seconds).
I need to pass select count(*) from X to variable how to do that?.
I was trying by SET VAR = SELECT...
INSERT INTO VAR SELECT...
I was trying to make a variable for statement which is directly executing
SET v_sql_stmt = 'INSERT INTO ' || VAR|| ' SELECT COUNT(*) FROM ' || P_TableName;
CALL DBC.SYSEXECSQL(v_sql_stmt);
It's probably really simple thing but I can't find good solution for that. Please help
You'll have to open a cursor to fetch the results since you are running dynamic SQL. There is a good example in the Teradata help doc on Dynamic SQL:
CREATE PROCEDURE GetEmployeeSalary
(IN EmpName VARCHAR(100), OUT Salary DEC(10,2))
BEGIN
DECLARE SqlStr VARCHAR(1000);
DECLARE C1 CURSOR FOR S1;
SET SqlStr = 'SELECT Salary FROM EmployeeTable WHERE EmpName = ?';
PREPARE S1 FROM SqlStr;
OPEN C1 USING EmpName;
FETCH C1 INTO Salary;
CLOSE C1;
END;
You can't use INTO in Dynamic SQL in Teradata.
As a workaround you need to do a cursor returning a single row:
DECLARE cnt BIGINT;
DECLARE cnt_cursor CURSOR FOR S;
SET v_sql_stmt = ' SELECT COUNT(*) FROM ' || P_TableName;
PREPARE S FROM v_sql_stmt;
OPEN cnt_cursor;
FETCH cnt_cursor INTO cnt;
CLOSE cnt_cursor;

JDBC - SQLITE Select to variable

I am trying to run a query / select statement and save it in a variable. I know how to get something specific from a specific column but not from counting rows.
This is working as I getting MYID specifically.
ResultSet MYIDrs = stmtCFG.executeQuery( "SELECT rowid, MYID from MYINDEX order by rowid desc limit 1;" );
MYID = MYIDrs.getString("MYID");
Now I am trying to count the rows that works in SQLite client but not in the jdbc as I can't figure out what to request.
this is what I have but is not resulting in what I am expecting.
ResultSet FILE_COUNTrs = stmtCFG.executeQuery( "SELECT count(*) from TABLE where MYID = '"+MYID+"';");
FILE_COUNT = FILE_COUNTrs.getString(?????);
problem or question is: What do I put in the ????? as I already tried everything.
I am expecting to see a number.
I am really sorry I found what I was looking for by assigning a name TOTAL
This is my code and it works...
ResultSet FILE_COUNTrs = stmtCFG.executeQuery( "SELECT count(*) AS TOTAL from TABLE where MYID = '"+MYID+"';");
FILE_COUNT = FILE_COUNTrs.getString("TOTAL");
You use wrong data type. COUNT(*) returns Integer type, Not String.
You can do like this without assigning a label for COUNT(*)
int FILE_COUNT = FILE_COUNTrs.getInt(1); // 1: is the column index of COUNT(*)

Sqlite DB Error - could not prepare statement

I am getting following error on insert statement for sqlite DB
could not prepare statement (1 near "undefined": syntax error)
I tried 2 variations of insert, for both error is same
var sql = "INSERT INTO Med(MedID) VALUES(?),";
sql += "['"+dataObj[i].MedID+"']";
var sql = "INSERT INTO Med(MedID) VALUES ('"+dataObj[i].MedID+"')";
tx.executeSql(sql);
The correct way to give parameters to an SQL statement is as follows:
var sql = "INSERT INTO Med(MedID) VALUES (?)";
tx.executeSql(sql, [dataObj[i].MedID]);
It looks like you are missing the space that is needed between the table name and the column names.
Try this:
var sql = "INSERT INTO Med (MedID) VALUES ('"+dataObj[i].MedID+"')";
tx.executeSql(sql);
Make sure your dataObj[i].MedID is also defined. Add a console.log(sql) before your executeSql statement to check the command before using it.

Inconsistent results of stored procedure execution - ASP.net code vs Direct SP call

Thanks in advance for anyone's help. This is mystery which is driving me crazyyyy :(.
IF I run this following stored procedure directly on SQL server 2008R2, it returns the desired rows. But if I call this via ASP.net(3.5) it returns empty data from the last Select statement in SP.
Is there any scoping involved in this regarding the temp table #_CalendarDate?
Stored Procedure:
USE[DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [WC].[spsGetDayCyclePeriod]
(
#Param_StartDate datetime,
#NumberOfDayRange int,
#Campus_Type varchar(2)
)
AS
DECLARE #DateRangeStart datetime
DECLARE #DateRangeEnd datetime
DECLARE #_CalendarDate TABLE (CollegeDate datetime)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET DATEFIRST 1
SELECT #DateRangeStart=max(CalendarDate) FROM [X].dbo.CalendarEvents
WHERE CalendarDate <= #Param_StartDate and left(CalendarType,1)= #Campus_Type
and (CalendarType <> #Campus_Type+'_H' and CalendarType<>'H'
and convert(INT, right(CalendarType, len(CalendarType)-3))>0)
SELECT #DateRangeEnd=min(CalendarDate) FROM [X].dbo.CalendarEvents
WHERE CalendarDate >= dateadd(day, #NumberOfDayRange-1, #Param_StartDate)
and left(CalendarType,1)= #Campus_Type and (CalendarType <> #Campus_Type+'_H'
and CalendarType<>'H' and convert(INT, right(CalendarType, len(CalendarType)-3))=0)
--Get all Dates within range
;WITH CollegeDate AS
(
SELECT #DateRangeStart AS DateValue
union all
SELECT dateadd(day, 1, DateValue)
FROM CollegeDate
WHERE dateadd(day, 1, DateValue) <= #DateRangeEnd
)
INSERT INTO #_CalendarDate (CollegeDate)
SELECT DateValue FROM CollegeDate OPTION (MAXRECURSION 0)
SELECT * from #_CalendarDate
END
ASP.Net code:
DataTable dayCycle = new DataTable();
var dateTimestr = startDate.ToString("yyyy-MM-dd HH:mm:ss");
using (SqlCommand sqlCommand = new SqlCommand("WC.spsGetDayCyclePeriod", new SqlConnection(Connection)))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
var range = endDate.Subtract(startDate).Days;
sqlCommand.Parameters.Add(new SqlParameter("#Param_StartDate", dateTimestr));
sqlCommand.Parameters.Add(new SqlParameter("#NumberOfDayRange", range));
sqlCommand.Parameters.Add(new SqlParameter("#Campus_Type", campus));
//dayCycle = SqlHelper.GetDataTableUsingSqlCommand(sqlCommand);
try
{
SqlDataAdapter _dap = new SqlDataAdapter(sqlCommand);
_dap.Fill(dayCycle);
}
catch (Exception ex)
{ throw new Exception(ex.ToString()); }
return dayCycle;
Pass #Param_StartDate as a date time object rather than a string.
Thanks everyone for help.
Solved the problem myself ! Hopefully it will help someone else as well in future. Here is the answer:
In above ASP.net code:
sqlCommand.Parameters.Add(new SqlParameter("#Campus_Type", campus));
campus is a enum type and when I was calling the above method with enum type I was actually passing the int value instead of string. So this is what I change to. This was confusing because when I was debugging my code I was using cursor on top of the #campus which basically calls toString so I was seeing the right value (which was wrong) the actual value was passed was number of enum.
sqlCommand.Parameters.Add(new SqlParameter("#Campus_Type", campus.ToString()));
And the above change solved the problem.
What I learned from this is Always...Always confirm that the arguments you intend to pass to SP is what SP is receiving so retrieve back your passed arguments by running the following before you do anything with Stored procedures...
Select #Your_Param1, #Your_Param2
And then check on code side that you are receiving what you are expecting.

Resources