I'm trying to execute a raw sql string using my custom Connection class..
(The Execute method simply executes the given sql statement..)
MyConnection.Execute(
"DECLARE #i int "
"SET #i = 0 "
"WHILE (#i < 10000) BEGIN "
"INSERT INTO my_table VALUES (1, 2, 3) "
"SET #i = #i + 1");
Running this statement gives me a syntax error:
Code = 80040e14
Code meaning = I
Source = ASEOLEDB
Description = [42000]
[ASEOLEDB] Incorrect syntax near '1'.
As you can see, I'm connecting to Sybase Adaptive Server Enterprise, which accepts T-SQL..
I'm assuming there is something wrong with my sql string,, or with how it's formatted?
Thanks
PS I'm sure there's nothing wrong with my "Execute" method, as a single line delete statement works fine..
i found this example in the web
there is no END at your code and no ; but the ';', i think, you don't need.
DECLARE #MyCounter int;
SET #MyCounter = 0;
WHILE (#MyCounter < 26)
BEGIN;
INSERT INTO TestTable VALUES (#MyCounter, CHAR( ( #MyCounter + ASCII('a') ) ) );
SET #MyCounter = #MyCounter + 1;
END;
BR
Alex
Related
I don't understand whats wrong with the code, I have read a lot of times but I can't find the error
pstmt = con->prepareStatement("SELECT (?) FROM votos WHERE id = (?)");
pstmt->setString(1, eleccion);
pstmt->setInt(2, p->getId());
res = pstmt->executeQuery();
while(res->next())
{
p->setVoto(res->getInt(1));
}
When the eleccion and id variables are Provincial and 1 respectively the getInt(1) function should return 1, but it returns 0.
The command (in the mysql command line):
SELECT Provincial from Votos WHERE id=1
Returns a table with one row and one column with the value 1
Side notes:
Spelling was checked
The getId() function works correctly
The compiler doesn't give any error
You can't use a placeholder in a prepared query for a column name. It's returning the value of the string eleccion, not using it as the name of a column in the table. You need to do string concatenation to substitute the column name.
std::string sql = std::string("SELECT `") + eleccion + "` FROM votos WHERE id = ?";
pstmt = con->prepareStatement(sql.c_str());
pstmt->setInt(1, p->getId());
res = pstmt->executeQuery();
while(res->next())
{
p->setVoto(res->getInt(1));
}
If the value of eleccion is coming from the user or some other untrusted source, make sure you validate it before concatenating, to prevent SQL injection.
I know the title is a mouth-full - sorry about that but trying to be specific here.
DB: MySql (technically Maria)
ColdFusion (technically Lucee: 5.x)
The array looks like the following:
NOTE: the outter most array only shows part of 2 and could continue through into the 30's.
I'm looking to perform a loop over the array to insert the elements marked as "string" in the image into the database using one query. Query has been trimmed for the sake of clarity and conciseness:
for (outer = 1; outer <= ArrayLen(myArray); outer++) {
local.currentrow = local.currentrow + 1;
for (inner = 1; inner <= ArrayLen(myArray[outer]); inner++) {
local.sql = "
INSERT INTO table (uuid, typeID, menuId, activityID, userID)
VALUES (
'#local.uuid#',
#myArray[outer][inner][1]#,
#myArray[outer][inner][2]#,
#myArray[outer][inner][3]#,
#arguments.formDataStruct.userID#
)";
queryExecute(local.sql);
}
}
I'm looking for something along this line but as written, it isn't working:
local.sql = "
INSERT INTO table (uuid, typeID, menuId, activityID, userID)
VALUES (
if (local.currentrow gt 1) {
,
}
for (outer = 1; outer <= ArrayLen(myArray); outer++) {
local.currentrow = local.currentrow + 1;
for (inner = 1; inner <= ArrayLen(myArray[outer]); inner++) {
'#local.uuid#',
'#myArray[outer][inner][1]#',
'#myArray[outer][inner][2]#',
'#myArray[outer][inner][3]#',
'#arguments.formDataStruct.userID#'
}
})
";
queryExecute(local.sql);
The error message I'm getting is
Element at position [1] doesn't exist in array
but if I perform a writedump[1][3][3] (e.g.), I'll get the value 24.
I would recommend against looping over an INSERT statement and rather just loop over VALUES to generate a single INSERT statement. A single INSERT will perform significantly faster, plus it will minimize the connections to your database.
Build out the list of values with something like:
for (var outer in arguments.inArray) {
for (var inner in outer) {
// Concat elements of inner array to a SQL VALUE string. If UUID is supposed to be a unique identity for the row, use Maria's uuid() instead of CF (or skip the UUID insert and let Maria do it).
// inArray elements and inUserID should be sanitized.
local.values &= "( uuid(), '" & inner[1] & "','" & inner[2] & "','" & inner[3] & "'," & local.userID & ")," ;
}
}
local.values = left(local.values,len(local.values)-1) ; // Get rid of the last comma.
local.sql = "INSERT INTO table (uuid, typeID, menuId, activityID, userID) VALUES " & local.values ;
After you've built up the SQL INSERT string, execute the query to INSERT the records. (You would probably build the above function differently to handle building the query string and parameters and then executing it all in one place.)
Don't forget to sanitize your array and other inputs. Does the array come from a source you control or is it user input?
https://trycf.com/gist/7ad6af1e84906b601834b0cc5ff5a392/lucee5?theme=monokai
http://dbfiddle.uk/?rdbms=mariadb_10.2&fiddle=d11f45f30723ba910c58a1e3f7a7c30b
I'm attempting to insert multiple rows into a DB2 database using c / c++ code like this:
EXEX SQL BEGIN DECLARE SECTION;
char inputArrayChar1 [3][10];
char inputArrayChar2 [3][10];
char inputArrayChar3 [3][10];
EXEX SQL END DECLARE SECTION;
for(int i = 0 ; i < 3 ; i++)
{
sprintf(inputArrayChar1[i] , "column1Data%d" , i + 1);
sprintf(inputArrayChar2[i] , "column2Data%d" , i + 1);
sprintf(inputArrayChar3[i] , "column3Data%d" , i + 1);
}
EXEC SQL INSERT INTO TABLETEST (COLUMN1 , COLUMN2 , COLUMN3)
VALUES(:inputArrayChar1 , :inputArrayChar2 ,inputArrayChar3);
run process DB result : only 1 row data , other 2 rows data not insert to DB.
Can anyone explain what could account for this?
I have inquiries to 1 case , need add ROWS syntax code like this:
EXEC SQL INSERT INTO TABLETEST (COLUMN1 , COLUMN2 , COLUMN3)
3 ROWS VALUES(:inputArrayChar1 , :inputArrayChar2 ,inputArrayChar3);
but use this syntax , Compiler issue is SQL0104N message "An unexpected token '3 ROWS' ....."
Can anyone explain what could account for this? Or I need add Environment variable to db ? or add Environment variable to Compiler Environment ?
thanks.
[Posting question from customer]
I would like to do periodic loads into SQL Data Warehouse using Polybase. My plan is to create a Stored Procedure that takes in the "LOCATION" parameter for Create External Table, but the parameter is failing due to syntax. Here's a sample of the code I've written:
alter PROCEDURE CETFromNewLocation
as
begin
Declare #location varchar(100)='data/2015/2015831';
Create External TABLE stg_tbl (
[DateId] int NULL
)
WITH (
LOCATION= #location,
DATA_SOURCE = my_external_source,
FILE_FORMAT = my_external_file_format,
REJECT_TYPE = VALUE,
REJECT_VALUE = 0
)
end
The error message I'm getting is:
> Parse error at line: 25, column: 16: Incorrect syntax near
> '#location'.
You cannot use variables in DDL statements. Try using dynamic sql - form the string for your DDL and execute it using sp_executesql stored procedure like below.
ALTER PROCEDURE CETFromNewLocation AS
BEGIN
DECLARE #location varchar(100)
SET #location = 'data/2015/2015831'
DECLARE #CreateExternalTableString varchar(100)
SET #CreateExternalTableString =
'Create External TABLE stg_tbl (
[DateId] int NULL
)
WITH (LOCATION = ' + #location + ',
DATA_SOURCE = my_external_source,
FILE_FORMAT = my_external_file_format,
REJECT_TYPE = VALUE,
REJECT_VALUE = 0
)'
EXEC sp_executesql #CreateExternalTableString
END
I have a table with 10,000 rows and I want to select the first 1000 rows and then select again and this time, the next set of rows, which is 1001-2001.
I am using the BETWEEN clause in order to select the range of values. I can also increment the values. Here is my code:
count = cursor.execute("select count(*) from casa4").fetchone()[0]
ctr = 1
ctr1 = 1000
str1 = ''
while ctr1 <= count:
sql = "SELECT AccountNo FROM ( \
SELECT AccountNo, ROW_NUMBER() OVER (ORDER BY Accountno) rownum \
FROM casa4 ) seq \
WHERE seq.rownum BETWEEN " + str(ctr) + " AND " + str(ctr1) + ""
ctr = ctr1 + 1
ctr1 = ctr1 + 1000
cursor.execute(sql)
sleep(2) #interval in printing of the rows.
for row in cursor:
str1 = str1 + '|'.join(map(str,row)) + '\n'
print "Records:" + str1 #var in storing the fetched rows from database.
print sql #prints the sql statement(str) and I can see that the var, ctr and ctr1 have incremented correctly. The way I want it.
What I want to achieve is using a messaging queue, RabbitMQ, I will send this rows to another database and I want to speed up the process. Selecting all and sending it to the queue returns an error.
The output of the code is that it returns 1-1000 rows correctly on the 1st but, on the 2nd loop, instead of 1001-2001 rows, it returns 1-2001 rows, 1-3001 and so on.. It always starts on 1.
I was able to recreate your issue with both pyodbc and pypyodbc. I also tried using
WITH seq (AccountNo, rownum) AS
(
SELECT AccountNo, ROW_NUMBER() OVER (ORDER BY Accountno) rownum
FROM casa4
)
SELECT AccountNo FROM seq
WHERE rownum BETWEEN 11 AND 20
When I run that in SSMS I just get rows 11 through 20, but when I run it from Python I get all the rows (starting from 1).
The following code does work using pyodbc. It uses a temporary table named #numbered, and might be helpful in your situation since your process looks like it would do all of its work using the same database connection:
import pyodbc
cnxn = pyodbc.connect("DSN=myDb_SQLEXPRESS")
crsr = cnxn.cursor()
sql = """\
CREATE TABLE #numbered (rownum INT PRIMARY KEY, AccountNo VARCHAR(10))
"""
crsr.execute(sql)
cnxn.commit()
sql = """\
INSERT INTO #numbered (rownum, AccountNo)
SELECT
ROW_NUMBER() OVER (ORDER BY Accountno) AS rownum,
AccountNo
FROM casa4
"""
crsr.execute(sql)
cnxn.commit()
sql = "SELECT AccountNo FROM #numbered WHERE rownum BETWEEN ? AND ? ORDER BY rownum"
batchsize = 1000
ctr = 1
while True:
crsr.execute(sql, [ctr, ctr + batchsize - 1])
rows = crsr.fetchall()
if len(rows) == 0:
break
print("-----")
for row in rows:
print(row)
ctr += batchsize
cnxn.close()