tags:

views:

2065

answers:

4

I tried running the following statement:

INSERT INTO VOUCHER (VOUCHER_NUMBER, BOOK_ID, DENOMINATION)
SELECT (a.number, b.ID, b.DENOMINATION) 
FROM temp_cheques a, BOOK b
WHERE a.number BETWEEN b.START_NUMBER AND b.START_NUMBER+b.UNITS-1;

which, as I understand it, should insert into VOUCHER each record from temp_cheques with the ID and DENOMINATION fields corresponding to entries in the BOOK table (temp_cheques comes from a database backup, which I'm trying to recreate in a different format). However, when I run it, I get an error:

Error: Operand should contain 1 column(s)
SQLState:  21000
ErrorCode: 1241

I'm running this in SQuirrel and have not had issues with any other queries. Is there something wrong with the syntax of my query?

EDIT:

The structure of BOOK is:

ID  int(11)
START_NUMBER    int(11)
UNITS   int(11)
DENOMINATION    double(5,2)

The structure of temp_cheques is:

ID  int(11)
number  varchar(20)
+2  A: 

Does B contain the UNITS column?

What is the table structure for temp_cheques and Book?

EDIT: As I said in comments, all the columns should be numeric when doing +/- and when comparing.
Does the following simple SELECT work?

SELECT b.START_NUMBER+b.UNITS-1 FROM Books B

shahkalpesh
Yes to the first question. and I've provided the relevant portions of the structure.
Elie
Can Between be applied to varchar? Also, what does b.START_NUMBER+b.UNITS-1 mean to a varchar column? I think you should cast it to numeric column and apply "-1" to it.
shahkalpesh
I would suggest modifying the title to have error message. That might help people searching for it (rather than generic mysql error thing)
shahkalpesh
I updated that to int(11) like the other field, but I get the same error.
Elie
try using it in a select. SELECT b.START_NUMBER+b.UNITS-1 FROM Books B - does this statement work?
shahkalpesh
Yes, that select works just fine
Elie
If that works, try putting the computing in a WHERE clause.e.g. SELECT b.ID, b.START_NUMBER+b.UNITS-1 FROM Books B WHERE b.START_NUMBER+b.UNITS-1 > 10000I am doubting that mysql doesn't allow computed columns in a where clause.
shahkalpesh
shahkalpesh
+1  A: 

I don't have a MySQL instance handy, but my first guess is the WHERE clause:

WHERE a.number BETWEEN b.START_NUMBER AND b.START_NUMBER+b.UNITS-1;

I imagine that the MySQL parser may be interpreting that as:

WHERE number
(BETWEEN start_number AND start_number) + units - 1

Try wrapping everything in parentheses, ie:

WHERE a.number BETWEEN b.START_NUMBER AND (b.START_NUMBER + b.UNITS - 1);
RJHunter
Just tried that, no difference.
Elie
It couldn't be; there's no other place for the "+b.UNITS-1" to go. It would either go in the BETWEEN statement, or throw an invalid token error.
lc
Unless it did parse it correctly (as far as the between statement goes) and my error is something different. All I know is that with or without the parentheses, I get the same error.
Elie
It couldn't be = this couldn't be the problem.
lc
+1  A: 

The final version of the query is as follows:

Set SQL_BIG_SELECTS = 1;
INSERT INTO VOUCHER (VOUCHER_NUMBER, BOOK_ID, DENOMINATION)
SELECT a.number, b.ID, b.DENOMINATION
FROM temp_cheques a, BOOK b
WHERE a.number BETWEEN b.START_NUMBER AND (b.START_NUMBER+b.UNITS-1);

The parsing of the BETWEEN statement required parentheses, the SELECT did not, and because of the size of the two tables (215000 records in temp_cheques, 8000 in BOOK) I was breaking a limit on the select size, requiring me to set SQL_BIG_SELECTS = 1.

Elie
Yeah, you were trying to do a cross reference on 1.7 billion combinations. Nothing wrong with it, of course, just with that many comparisons, it wanted to make sure you REALLY wanted to do it.
lc
at least I won't have to do this again... and it only took about 5 seconds to run.
Elie
+1  A: 

Try removing the parenthesis from the SELECT clause. From Microsoft TechNet, the correct syntax for an INSERT statement using a SELECT clause is the following.

INSERT INTO MyTable  (PriKey, Description)
       SELECT ForeignKey, Description
       FROM SomeView


The error you're getting, "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay.", is actually correct, assuming you have many rows in both BOOK and temp_cheques. You are trying to query all rows from both tables and make a cross-reference, resulting in an m*n size query. SQL Server is trying to warn you of this, before performing a potentially long operation.

Set SQL_BIG_SELECTS = 1 before running this statement, and try again. It should work, but note that this operation may take a long time.

lc