Неверное поле count или ошибка синтаксиса

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

lingo's user avatar

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

Taalaibek Ashirov's user avatar

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 Mason's user avatar

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's user avatar

Tim Schmelter

447k72 gold badges684 silver badges935 bronze badges

answered Dec 4, 2015 at 13:39

M.Ali's user avatar

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

snyderj's user avatar

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 Evans's user avatar

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.

Внешние источники данных

Я
   BubbleGumm

15.08.16 — 13:11

Есть таблица на скл сервере для хранения внешних файлов, поле данных с типом varbinary(max)

Из 1с(8.3.8.1479) пытаюсь записать данные. Лезет ошибка

Ошибка ODBC. SQLSTATE: 07002

Номер ошибки: 0

Описание: [Microsoft][ODBC SQL Server Driver]Неверное поле COUNT или ошибка синтаксиса

Что тут не так?

   BubbleGumm

1 — 15.08.16 — 13:12

Если не устанавливаю это поле, то все ОК

   Зая Бусечка

2 — 15.08.16 — 13:13

запрос не показываешь.

и вообще — кривым инструментом пользуешься.

   BubbleGumm

3 — 15.08.16 — 13:16

Запись через объектные данные

    Вложение = ВнешниеИсточникиДанных.Attachments.Таблицы.dbo_Attachments.СоздатьОбъект();

    Вложение.Name = «Имя»;

    Вложение.MailDocument = Новый УникальныйИдентификатор();

    ДД = Новый ДвоичныеДанные(«C:UsersАдминистраторDesktopSQL_tables.epf»);

    Вложение.Data = ДД;

    Вложение.Записать();

   BubbleGumm

4 — 15.08.16 — 13:24

Вообще как записать двоичные данные во внешний источник?

   Aleksey

5 — 15.08.16 — 13:30

   BubbleGumm

6 — 15.08.16 — 13:32

(5) И?

   shuhard

7 — 15.08.16 — 13:46

(6) и там объяснено, почему нельзя писать в поле Count

   BubbleGumm

8 — 15.08.16 — 13:50

(7) Какое поле Count??

Я пишу в поле под именем Data, если под Count подразумевается ключевое поле счетчик, то никто в него ничего не пишет

   DmitrO

9 — 15.08.16 — 13:52

(7)поле тут непричем.

Это ошибка драйвера ODBC, а не сервера. И говорит она о том, что платформа не правильно работает с драйвером ODBC.

(0)жалуйтесь на хотлайн или testplatform

   BubbleGumm

10 — 15.08.16 — 13:55

(9) С уникальным идентификатором тем не менее все ОК, а он тоже имеет тип двоичные данные

   DmitrO

11 — 15.08.16 — 13:59

(10)у вас в поле Data так называемые «длинные» данные, чтобы их передать параметром запроса нужно применить особую технику работы с драйвером ODBC: SQL_DATA_AT_EXEC.

Так вот разработчики платформы попросту чета накосяпурили там.. ну ничего, поправят.. когда-нибудь.

   BubbleGumm

12 — 15.08.16 — 14:00

(11) Да и фиг с ними, переделал тип на скл в неограниченную строку, пишу через Base64Строка

   DmitrO

13 — 15.08.16 — 14:02

(12)обошел, молодец..

Но бог плачет, когда об ошибках платформы не сообщают разработчикам.

  

BubbleGumm

14 — 15.08.16 — 14:03

да время появится, напишу возможно

    msm.ru

    Нравится ресурс?

    Помоги проекту!

    !
    информация о разделе

    user posted image Данный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных — обсуждаем в разделе «Базы данных: общие вопросы». Убедительная просьба — соблюдать «Правила форума» и не пренебрегать «Правильным оформлением своих тем». Прежде, чем создавать тему, имеет смысл заглянуть в раздел «Базы данных: FAQ», возможно там уже есть ответ.

    >
    Хранимая процедура
    , Все понятно но не получается…

    • Подписаться на тему
    • Сообщить другу
    • Скачать/распечатать тему

      


    Сообщ.
    #1

    ,
    28.10.04, 11:26

      Знаю что тема уже забитая и нашел много примеров по работе с ХП, однако, никак не получется реализовать! Помагите найти ошибку плиз :( !
      ИТАК простая ХП на SQL Server 2000 c выходным параметром:

      ExpandedWrap disabled

        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:
      .h файл

      ExpandedWrap disabled

        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 файл

      ExpandedWrap disabled

        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

        }

      Вызываю:

      ExpandedWrap disabled

        RecordProcedure pro;

        pro.n_n=1;

        pro.Open(CRecordset::snapshot,»{?=CALL [Ginetic](?)}»);

        int n=pro.n_n;

      Выдает сообщение:НЕПРАВИЛЬНОЕ ПОЛЕ COUNT ИЛИ ОШИБКА СИНТАКСИСА!

      В чем я ошибся? :wall:


      Green



      Сообщ.
      #2

      ,
      28.10.04, 11:59

        Senior Member

        ****

        Рейтинг (т): 48

        Во первых, я бы сделал так

        ExpandedWrap disabled

          CREATE PROCEDURE [Ginetic]

          @n  int

          AS

          BEGIN

          DECLARE @STR nvarchar(50)

          SET @STR=user

          if @STR=’Operator’ SELECT 1

            else   SELECT 2

          END

          GO

        И во вторых, наверное, так правильнее будет

        ExpandedWrap disabled

          pro.Open(CRecordset::snapshot,»{EXEC [Ginetic](?)}»);


        StavR



        Сообщ.
        #3

        ,
        28.10.04, 12:14

          Цитата

          И во вторых, наверное, так правильнее будет
          pro.Open(CRecordset::snapshot,»{EXEC [Ginetic](?)}»);

          ну это врядли правильно!

          Хорошо я сделал запрос как предлагает GreenElf, при этом поменял:

          ExpandedWrap disabled

            void RecordProcedure::DoFieldExchange(CFieldExchange* pFX)

            {

                //{{AFX_FIELD_MAP(RecordProcedure)

                pFX->SetFieldType(CFieldExchange::inputParam);//сменил на инпут

                RFX_Long(pFX, _T(«[@n]»), n_n);

                //}}AFX_FIELD_MAP

            }

          и

          ExpandedWrap disabled

            pro.Open(CRecordset::snapshot,»{CALL [Ginetic](?)}»);

          Опять ошибка:»Ни один столбец не связан до вызова SQLFatchScroll/SQLExtendedFetch»

          Добавлено 28.10.04, 12:40
          НЕ уж-то никто из присутствующих с БД не работает? :blink:


          Green



          Сообщ.
          #4

          ,
          28.10.04, 13:08

            Senior Member

            ****

            Рейтинг (т): 48

            Ой, блин, накосячил как обычно. Вот так надо было…имя полю присвоить забыл.

            ExpandedWrap disabled

              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



            Сообщ.
            #5

            ,
            28.10.04, 13:16

              Все одно и тоже: «Ни один столбец не был связан до вызова SQLFatchScroll/SQLExtendedFetch» :'(

              Сообщение отредактировано: StavR — 28.10.04, 13:18


              Green



              Сообщ.
              #6

              ,
              28.10.04, 13:30

                Senior Member

                ****

                Рейтинг (т): 48

                У тебя DoFieldExchange как определена? Покажи код, если можно.


                StavR



                Сообщ.
                #7

                ,
                29.10.04, 08:19

                  Что значит как определена? Код описан выше! <_<

                  Так что ни у кого нет больше соображений :blink: ????


                  Leprecon



                  Сообщ.
                  #8

                  ,
                  29.10.04, 08:34


                    Green



                    Сообщ.
                    #9

                    ,
                    29.10.04, 08:44

                      Senior Member

                      ****

                      Рейтинг (т): 48

                      Сорри, ступнячил опять.
                      ТОгда где описание
                      CFieldParam::outputColumn и полей данных?
                      И еще: в конструкторе класса нужно корректно определить m_nFields
                      Примерно так:

                      ExpandedWrap disabled

                        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

                        


                      Сообщ.
                      #10

                      ,
                      29.10.04, 09:02

                        Не совсем согласен что тема по SQL SErver 2000 так как проблема в реализации на С!!! ;)
                        НУ да ладно!

                        GreenElf ты полностью прав!

                        Цитата

                        ТОгда где описание
                        CFieldParam::outputColumn и полей данных?
                        И еще: в конструкторе класса нужно корректно определить m_nFields

                        дело в том что у меня процедура не возвращает полей данных m_nFields=0, в этом и ошибка!
                        Для этого случая надо сделать так:

                        ExpandedWrap disabled

                          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;

                          }

                        Извеняюсь что сразу не обратил на это внимания!
                        GreenElf +1 за правильное направление!!!

                        Сообщение отредактировано: StavR — 29.10.04, 09:04

                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                        0 пользователей:

                        • Предыдущая тема
                        • Базы данных: SQL
                        • Следующая тема

                        Рейтинг@Mail.ru

                        [ 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, @p5

                        exec sp_cursorclose 180150003 go

                        Понравилась статья? Поделить с друзьями:
                      • Неверное оформление прямой речи какая это ошибка
                      • Неверное окончание это какая ошибка
                      • Неверное выделение word ошибка как исправить
                      • Неверно указана единица измерения как убрать ошибку
                      • Не являются ошибками слушания