What would be the error when I get following error message
Fatal error: Uncaught exception ‘PDOException’ with message ‘SQLSTATE[07002]: [Microsoft][ODBC Driver 11 for SQL Server]COUNT field incorrect or syntax error’…
This is the query I’m using
$sql = $pdo->prepare("SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->execute();
I have searched questions in SO, but no one was similar or helpful.
Thanks in advance.
Edit: This query is working fine when executing it with Microsoft SQL Server Management Studio, but when using PDO, I’m getting the error.
asked Dec 4, 2015 at 13:35
lingolingo
1,8386 gold badges28 silver badges54 bronze badges
4
The number of parameters specified in SQLBindParameter was less than
the number of parameters in the SQL statement contained in
*StatementText. SQLBindParameter was called with ParameterValuePtr set to a null pointer, StrLen_or_IndPtr not set to SQL_NULL_DATA or
SQL_DATA_AT_EXEC, and InputOutputType not set to SQL_PARAM_OUTPUT, so
that the number of parameters specified in SQLBindParameter was
greater than the number of parameters in the SQL statement contained
in *StatementText. SQLExecute Function
placeholders must have unique names even if they have the same value
$sql = $pdo->prepare("SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid2 AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->bindValue(':artid2', $productId);
$sql->execute();
answered Dec 8, 2015 at 14:42
3
Another possibility, if you want to avoid supplying data multiple times (replace the datatype of @artid with the correct data type):
$sql = $pdo->prepare("DECLARE @artid int = :artid
SELECT stockamount, stockname, stockbalance.stockid, SUM(ABS(reservationtransaction.stockquantity)) AS reservedamount FROM stockbalance
JOIN stock ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction ON reservationtransaction.articleid = @artid
WHERE stockbalance.articleid = @artid AND ((changeddate > DATEADD(yy,-1,GETDATE()) AND inventorydate > DATEADD(yy,-1,GETDATE())) OR stockbalance.stockamount <> 0)
GROUP BY stockbalance.stockid");
$sql->bindValue(':artid', $productId);
$sql->execute();
This will only work in an RDBMS that supports DECLARE statements.
answered Mar 11, 2018 at 22:51
Aaron MasonAaron Mason
3003 silver badges11 bronze badges
All the columns that are not in any arithmetic function must go in the GROUP BY
clause. see below:
SELECT stockamount,
stockname,
stockbalance.stockid,
Sum(Abs(reservationtransaction.stockquantity)) AS reservedamount
FROM stockbalance
INNER JOIN stock
ON stockbalance.stockid = stock.stockid
LEFT JOIN reservationtransaction
ON reservationtransaction.articleid = :artid
WHERE stockbalance.articleid = :artid
AND ( ( changeddate > Dateadd(yy, -1, Getdate())
AND inventorydate > Dateadd(yy, -1, Getdate()) )
OR stockbalance.stockamount <> 0 )
GROUP BY stockamount,
stockname,
stockbalance.stockid
Tim Schmelter
447k72 gold badges684 silver badges935 bronze badges
answered Dec 4, 2015 at 13:39
M.AliM.Ali
67.5k13 gold badges99 silver badges124 bronze badges
1
While GROUP BY is often the culprit for a COUNT issue, I ran into the subject error in SSRS and it was due to a mismatch between the SSRS dataset query and the parameters. The resolution was to ensure each WHERE in the query had a corresponding parameter for the dataset. (I had missed one.)
answered May 1, 2019 at 16:22
snyderjsnyderj
8017 silver badges6 bronze badges
We had this error when a Django filter statement was trying to substitute more parameters in a query than could be handled by the DB binary. Our query looked roughly like this:
select name, age from Employee where emp_id in (%s)
from a Django statement
Employee.objects.filter(emp_id__in=employee_ids)
The list of emp_id was about 2,100 elements. (The character length of the params substituted was about 10,500).
The hack was to filter in parts and recombine the subsets.
answered Mar 18, 2022 at 9:09
Noel EvansNoel Evans
8,0238 gold badges48 silver badges58 bronze badges
At the time this question was asked, pandas 0.23.0 had just been released. That version changed the default behaviour of .to_sql()
from calling the DBAPI .executemany()
method to constructing a table-value constructor (TVC) that would improve upload speed by inserting multiple rows with a single .execute()
call of an INSERT statement. Unfortunately that approach often exceeded T-SQL’s limit of 2100 parameter values for a stored procedure, leading to the error cited in the question.
Shortly thereafter, a subsequent release of pandas added a method=
argument to .to_sql()
. The default – method=None
– restored the previous behaviour of using .executemany()
, while specifying method="multi"
would tell .to_sql()
to use the newer TVC approach.
Around the same time, SQLAlchemy 1.3 was released and it added a fast_executemany=True
argument to create_engine()
which greatly improved upload speed using Microsoft’s ODBC drivers for SQL Server. With that enhancement, method=None
proved to be at least as fast as method="multi"
while avoiding the 2100-parameter limit.
So with current versions of pandas, SQLAlchemy, and pyodbc, the best approach for using .to_sql()
with Microsoft’s ODBC drivers for SQL Server is to use fast_executemany=True
and the default behaviour of .to_sql()
, i.e.,
connection_uri = (
"mssql+pyodbc://scott:tiger^5HHH@192.168.0.199/db_name"
"?driver=ODBC+Driver+17+for+SQL+Server"
)
engine = create_engine(connection_uri, fast_executemany=True)
df.to_sql("table_name", engine, index=False, if_exists="append")
This is the recommended approach for apps running on Windows, macOS, and the Linux variants that Microsoft supports for its ODBC driver. If you need to use FreeTDS ODBC, then .to_sql()
can be called with method="multi"
and chunksize=
as described below.
(Original answer)
Prior to pandas version 0.23.0, to_sql
would generate a separate INSERT for each row in the DataTable:
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
0,N'row000'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
1,N'row001'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
2,N'row002'
Presumably to improve performance, pandas 0.23.0 now generates a table-value constructor to insert multiple rows per call
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6),@P3 int,@P4 nvarchar(6),@P5 int,@P6 nvarchar(6)',
N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2), (@P3, @P4), (@P5, @P6)',
0,N'row000',1,N'row001',2,N'row002'
The problem is that SQL Server stored procedures (including system stored procedures like sp_prepexec
) are limited to 2100 parameters, so if the DataFrame has 100 columns then to_sql
can only insert about 20 rows at a time.
We can calculate the required chunksize
using
# df is an existing DataFrame
#
# limit based on sp_prepexec parameter count
tsql_chunksize = 2097 // len(df.columns)
# cap at 1000 (limit for number of rows inserted by table-value constructor)
tsql_chunksize = 1000 if tsql_chunksize > 1000 else tsql_chunksize
#
df.to_sql('tablename', engine, index=False, if_exists='replace',
method='multi', chunksize=tsql_chunksize)
However, the fastest approach is still likely to be:
-
dump the DataFrame to a CSV file (or similar), and then
-
have Python call the SQL Server
bcp
utility to upload that file into the table.
Внешние источники данных |
Я |
15.08.16 — 13:11
Есть таблица на скл сервере для хранения внешних файлов, поле данных с типом varbinary(max)
Из 1с(8.3.8.1479) пытаюсь записать данные. Лезет ошибка
Ошибка ODBC. SQLSTATE: 07002
Номер ошибки: 0
Описание: [Microsoft][ODBC SQL Server Driver]Неверное поле COUNT или ошибка синтаксиса
Что тут не так?
1 — 15.08.16 — 13:12
Если не устанавливаю это поле, то все ОК
2 — 15.08.16 — 13:13
запрос не показываешь.
и вообще — кривым инструментом пользуешься.
3 — 15.08.16 — 13:16
Запись через объектные данные
Вложение = ВнешниеИсточникиДанных.Attachments.Таблицы.dbo_Attachments.СоздатьОбъект();
Вложение.Name = «Имя»;
Вложение.MailDocument = Новый УникальныйИдентификатор();
ДД = Новый ДвоичныеДанные(«C:UsersАдминистраторDesktopSQL_tables.epf»);
Вложение.Data = ДД;
Вложение.Записать();
4 — 15.08.16 — 13:24
Вообще как записать двоичные данные во внешний источник?
5 — 15.08.16 — 13:30
6 — 15.08.16 — 13:32
(5) И?
7 — 15.08.16 — 13:46
(6) и там объяснено, почему нельзя писать в поле Count
8 — 15.08.16 — 13:50
(7) Какое поле Count??
Я пишу в поле под именем Data, если под Count подразумевается ключевое поле счетчик, то никто в него ничего не пишет
9 — 15.08.16 — 13:52
(7)поле тут непричем.
Это ошибка драйвера ODBC, а не сервера. И говорит она о том, что платформа не правильно работает с драйвером ODBC.
(0)жалуйтесь на хотлайн или testplatform
10 — 15.08.16 — 13:55
(9) С уникальным идентификатором тем не менее все ОК, а он тоже имеет тип двоичные данные
11 — 15.08.16 — 13:59
(10)у вас в поле Data так называемые «длинные» данные, чтобы их передать параметром запроса нужно применить особую технику работы с драйвером ODBC: SQL_DATA_AT_EXEC.
Так вот разработчики платформы попросту чета накосяпурили там.. ну ничего, поправят.. когда-нибудь.
12 — 15.08.16 — 14:00
(11) Да и фиг с ними, переделал тип на скл в неограниченную строку, пишу через Base64Строка
13 — 15.08.16 — 14:02
(12)обошел, молодец..
Но бог плачет, когда об ошибках платформы не сообщают разработчикам.
BubbleGumm
14 — 15.08.16 — 14:03
да время появится, напишу возможно
|
|
|
информация о разделе
Данный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных — обсуждаем в разделе «Базы данных: общие вопросы». Убедительная просьба — соблюдать «Правила форума» и не пренебрегать «Правильным оформлением своих тем». Прежде, чем создавать тему, имеет смысл заглянуть в раздел «Базы данных: FAQ», возможно там уже есть ответ. |
Хранимая процедура
, Все понятно но не получается…
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Знаю что тема уже забитая и нашел много примеров по работе с ХП, однако, никак не получется реализовать! Помагите найти ошибку плиз CREATE PROCEDURE [Ginetic] @n int OUTPUT AS DECLARE @STR nvarchar(50) SET @STR=user if @STR=’Operator’ set @n=1 else set @n=2 GO Подключаюсь через Recordset: class RecordProcedure : public CRecordset { public: RecordProcedure(CDatabase* pDatabase = NULL); DECLARE_DYNAMIC(RecordProcedure) // Field/Param Data //{{AFX_FIELD(RecordProcedure, CRecordset) long n_n; //}}AFX_FIELD … .cpp файл RecordProcedure::RecordProcedure(CDatabase* pdb) : CRecordset(pdb) { //{{AFX_FIELD_INIT(RecordProcedure) n_n = 0; m_nFields = 0; //}}AFX_FIELD_INIT m_nParams = 1; m_nDefaultType = snapshot; } CString RecordProcedure::GetDefaultConnect() { return _T(«ODBC;DSN=Generic»); } CString RecordProcedure::GetDefaultSQL() { return _T(«»); } void RecordProcedure::DoFieldExchange(CFieldExchange* pFX) { //{{AFX_FIELD_MAP(RecordProcedure) pFX->SetFieldType(CFieldExchange::inoutParam); RFX_Long(pFX, _T(«[@n]»), n_n); //}}AFX_FIELD_MAP } Вызываю: RecordProcedure pro; pro.n_n=1; pro.Open(CRecordset::snapshot,»{?=CALL [Ginetic](?)}»); int n=pro.n_n; Выдает сообщение:НЕПРАВИЛЬНОЕ ПОЛЕ COUNT ИЛИ ОШИБКА СИНТАКСИСА! В чем я ошибся? |
Green |
|
Senior Member Рейтинг (т): 48 |
Во первых, я бы сделал так CREATE PROCEDURE [Ginetic] @n int AS BEGIN DECLARE @STR nvarchar(50) SET @STR=user if @STR=’Operator’ SELECT 1 else SELECT 2 END GO И во вторых, наверное, так правильнее будет pro.Open(CRecordset::snapshot,»{EXEC [Ginetic](?)}»); |
StavR |
|
Цитата
И во вторых, наверное, так правильнее будет ну это врядли правильно! Хорошо я сделал запрос как предлагает GreenElf, при этом поменял: void RecordProcedure::DoFieldExchange(CFieldExchange* pFX) { //{{AFX_FIELD_MAP(RecordProcedure) pFX->SetFieldType(CFieldExchange::inputParam);//сменил на инпут RFX_Long(pFX, _T(«[@n]»), n_n); //}}AFX_FIELD_MAP } и pro.Open(CRecordset::snapshot,»{CALL [Ginetic](?)}»); Опять ошибка:»Ни один столбец не связан до вызова SQLFatchScroll/SQLExtendedFetch» Добавлено 28.10.04, 12:40 |
Green |
|
Senior Member Рейтинг (т): 48 |
Ой, блин, накосячил как обычно. Вот так надо было…имя полю присвоить забыл. CREATE PROCEDURE [Ginetic] @n int AS BEGIN DECLARE @STR nvarchar(50) SET @STR=user if @STR=’Operator’ SELECT 1 AS Result else SELECT 2 AS Result END GO А вообще говоря, хранимки через EXEC вызываются…насколько мои мозги помнят. Ну, да это не существенно. |
StavR |
|
Все одно и тоже: «Ни один столбец не был связан до вызова SQLFatchScroll/SQLExtendedFetch» Сообщение отредактировано: StavR — 28.10.04, 13:18 |
Green |
|
Senior Member Рейтинг (т): 48 |
У тебя DoFieldExchange как определена? Покажи код, если можно. |
StavR |
|
Что значит как определена? Код описан выше! Так что ни у кого нет больше соображений |
Leprecon |
|
Green |
|
Senior Member Рейтинг (т): 48 |
Сорри, ступнячил опять. void RecordProcedure::DoFieldExchange(CFieldExchange* pFX) { pFX->SetFieldType(CFieldExchange::inputParam);//сменил на инпут RFX_Long(pFX, _T(«[@n]»), n_n); pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Long(pFX, _T(«Result»), m_nResult); } Извини, с MFC у меня не супер. Да , и комментарии тоже… Сообщение отредактировано: GreenElf — 29.10.04, 08:46 |
StavR |
|
Не совсем согласен что тема по SQL SErver 2000 так как проблема в реализации на С!!! GreenElf ты полностью прав! Цитата
ТОгда где описание дело в том что у меня процедура не возвращает полей данных m_nFields=0, в этом и ошибка! void StoredProcedure::Move( long nRows, WORD wFetchType ) { // Protection so that if the procedure returns no result sets, no // fetch operations are attempted. if (m_nFields) CRecordset::Move(nRows, wFetchType); else m_bBOF = m_bEOF = TRUE; }
Извеняюсь что сразу не обратил на это внимания! Сообщение отредактировано: StavR — 29.10.04, 09:04 |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Базы данных: SQL
- Следующая тема
[ Script execution time: 0,0397 ] [ 15 queries used ] [ Generated: 5.06.23, 05:31 GMT ]
Я получаю эту ошибку, когда пытаюсь вызвать хранимую процедуру в QT с помощью QODBC:
QODBCResult :: exec: Не удалось выполнить оператор: «[Microsoft] [драйвер SQL Server ODBC] Поле COUNT неверно или синтаксическая ошибка
Количество параметров верное, синтаксис выглядит мне хорошо. Процедура выполняется отлично в Management Studio. Что может быть проблемой?
QSqlQuery query(db1);
query.exec("SELECT * from Teachers"); //test query
TableWidget *table = ui->tableWidget;
for (int i = 0; i < table->rowCount(); i++)
{
QComboBox *combo = static_cast<QComboBox*>(table->cellWidget(i,0));
qDebug() << query.prepare("{CALL add_syllabus_line (?,?,?,?,?,?,?,?,?)}");
query.bindValue("teacher_name", teacherName);
query.bindValue("subject_name", "????");
query.bindValue("temporary_name", ratingName);
query.bindValue("type_name", combo->currentText());
query.bindValue("activity_name", table->item(i, 1)->text());
query.bindValue("min_score", table->item(i, 2)->text().toInt());
if (propertiesInstance.fixed) query.bindValue("max_score", 0);
else query.bindValue("max_score", table->item(i, 3)->text().toInt());
query.bindValue("max_score_exists", propertiesInstance.fixed);
query.bindValue("evaluation_by_exam", propertiesInstance.exam);
if (!query.exec())
{
qDebug() << query.lastError();
}
}
Процедура:
ALTER PROCEDURE [dbo].[add_syllabus_line]
@teacher_name NVARCHAR(50),
@subject_name NVARCHAR(50),
@temporary_name NVARCHAR(50),
@type_name NVARCHAR(50),
@activity_name NVARCHAR(50),
@min_score int,
@max_score int,
@max_score_exists bit,
@evaluation_by_exam bit
AS
BEGIN
SET NOCOUNT ON;
DECLARE @teacher_id int;
DECLARE @subject_id int;
DECLARE @type_id int;
SELECT @teacher_id = Teacher_id FROM Teachers WHERE Teacher_name = @teacher_name;
SELECT @type_id = Activity_type_id FROM Activity_types WHERE Activity_type_name = @type_name;
SELECT @subject_id = subject_id FROM Subjects WHERE Subject_name = @subject_name;
INSERT INTO Syllabi (Teacher_id,
Subject_id,
Temporary_name,
Activity_type_id,
Activity_title,
Activity_min_score,
Activity_max_score,
Max_score_exists,
Evaluation_by_exam) VALUES (@teacher_id,
@subject_id,
@temporary_name,
@type_id,
@activity_name,
@min_score,
@max_score,
@max_score_exists,
@evaluation_by_exam);
END
query.prepare
возвращает true.
Я запускаю трассировку профилировщика, и запрос там даже не показывает, только тестовый.
выберите 504, c.name, c.description, c.definition from master.dbo.syscharsets c где c.id = convert (tinyint, databasepropertyex (db_name(), ‘sqlcharset’)) go
exec sp_datatype_info 11 go
SET QUOTED_IDENTIFIER ON go
declare @p1 int set @p1 = 180150003
declare @p3 int
set @p3 = 8 declare @p4 int set @p4 = 1 declare @p5 int set @p5 = 3 exec sp_cursoropen @p1 output, N’SELECT * from Teachers ‘, @p3 output, @p4 output, @p5 output select @p1, @p3, @p4, @p5exec sp_cursorclose 180150003 go