Skip to content

bulkcopy accepts four-part table names that SQL Server always rejects #843

Open

Description

Describe the bug

The 1.16.0 bulk copy identifier parser allows up to four name parts (MAX_PARTS is 4), so cursor.bulkcopy() accepts server.database.schema.table. SQL Server doesn't allow a server prefix on a bulk insert target, so every four-part name fails with error 117 after metadata lookup starts. A five-part name fails earlier, in the driver, with a clear usage error.

Exception message:
RuntimeError: Sql Error: 117: Class 15: State 1: The object name 'dlevy-sql25.test1.dbo.fp116' contains more than the maximum number of prefixes. The maximum is 2. on dlevy-sql25 in  at line 1

For comparison, a five-part name:

RuntimeError: Failed to retrieve destination metadata: Usage Error: Too many identifier parts: 5 (maximum is 4)

To reproduce

import os
import mssql_python

conn = mssql_python.connect(os.environ["SQL_CONNECTION_STRING"], timeout=30)
cur = conn.cursor()
cur.execute("CREATE TABLE dbo.fp116 (i int)")
conn.commit()

server = cur.execute("SELECT @@SERVERNAME").fetchval()
try:
    cur.bulkcopy(f"[{server}].test1.dbo.fp116", [(1,)])
except Exception as e:
    print(type(e).__name__, e)

try:
    cur.bulkcopy("a.b.c.d.e", [(1,)])
except Exception as e:
    print(type(e).__name__, e)

cur.execute("DROP TABLE dbo.fp116")
conn.commit()

Expected behavior

The parser should allow at most three parts for a bulk copy target and reject a four-part name with the same kind of usage error it gives for five parts, before it contacts the server. The current limit of four suggests linked-server targets work, but they can't.

Further technical details

Python version: 3.14.0
mssql-python: 1.16.0 (pip), default msodbcsql18 provider
SQL Server version: SQL Server 2025 (RTM-CU9) 17.0.5005.3, Enterprise Edition, EngineEdition 3
Operating system: Windows 11

Additional context

Found while documenting the 1.16.0 bulk copy identifier changes in MicrosoftDocs/sql-docs-pr#38337. The docs now list one-part through three-part names and say that SQL Server rejects the four-part form.

Activity

  1. dlevy-msft-sql commented on Oct 13, 2026

    @dlevy-msft-sql
    ContributorAuthor

    I checked whether this is specific to mssql-python. It isn't: SQL Server rejects a server prefix on any bulk copy target. Tested against SQL Server 2025 (17.0.5005.3) with target [dlevy-sql25].test1.dbo.fp4:

    Driver Three-part name Four-part name
    mssql-python 1.16.0 OK Sent to server, error 117 ("The maximum is 2.")
    Microsoft.Data.SqlClient 7.1.1 OK Sent to server, error 117
    go-mssqldb 1.11.2 OK Sent to server, error 117
    bcp (ODBC Driver 17) OK Rejected client-side: "A valid table name is required for in, out, or format options."

    The ask stands. bcp already rejects the name before connecting, and mssql-python can do the same by capping the parser at three parts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: bulk-copyIssues in cursor.bulkcopy()triage neededFor new issues, not triaged yet.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions