Skip to main content

A utility to run fast BCP bulk inserts from a Pandas DataFrame, including CSV and high-speed native format.

Project description

Python BCP Utility (py-bcp-utils)

PyPI version License: MIT

A Python utility to run the SQL Server bcp (Bulk Copy Program) command using a Pandas DataFrame as the source.

This package provides two methods for high-speed bulk inserts:

  1. Standard (CSV): A simple, wrapper that saves the DataFrame to a temporary CSV and bulk inserts it.

  2. Native Format: An ultra-performant method that converts the DataFrame to bcp's native binary format in memory, bypassing the CSV step for massive speed gains.

Key Features

  • Bulk insert pandas.DataFrame objects directly into SQL Server.

  • Bypasses pd.to_sql() for significant performance improvements.

  • Simple Method (bulk_insert_bcp): Easy-to-use function that relies on a temporary CSV.

  • Native Method (bulk_insert_bcp_native): Extremely fast function that writes data directly to SQL Server's native binary format. Ideal for inserting millions of rows.

  • Supports both SQL Server Authentication (username/password) and Trusted Connections (Windows Authentication).

Requirements

  1. Python 3.8+

  2. pandas & numpy (will be installed automatically)

  3. bcp Utility: The SQL Server bcp command-line utility must be installed on your system and available in your shell's PATH.

    • On Windows, this is typically installed with SQL Server Management Studio (SSMS) or the Microsoft Command Line Utilities for SQL Server.

Installation

Once the package is published to the real PyPI, you can install it with:

Bash

pip install py-bcp-utils

Native Format Supported Types

The high-performance bulk_insert_bcp_native function currently supports the following SQL Server data types. You must ensure the type specified in your table_schema dictionary matches one of the following strings (case-insensitive):

  • Integer Types:

    • BIGINT
    • INT
    • SMALLINT
    • TINYINT
    • BIT (converts True/False/None)
  • Floating-Point Types:

    • FLOAT (SQL FLOAT(53))
    • REAL (SQL FLOAT(24))
  • String Types:

    • VARCHAR
    • NVARCHAR
  • Date/Time Types:

    • DATE: Accepts a pandas datetime column but truncates the time component. Intended for SQL DATE columns.
    • DATETIME2: Accepts a pandas datetime column and preserves the full timestamp (up to 100ns precision). Intended for SQL DATETIME2(7) columns.

Support for other types (like DECIMAL/NUMERIC) will be added in future versions.

Usage

You have two functions to choose from, depending on your performance needs.

1. Standard Insert (Simple, CSV-based)

This is the easiest method. It's reliable and great for most use cases. It works by saving the DataFrame to a temporary CSV file.

Python

import pandas as pd
import logging
from bcp_utils import bulk_insert_bcp

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

data = {
    'column1': [1, 2, 3],
    'column2': ['apple', 'banana', 'orange'],
    'column3': [10.5, 20.1, 30.2]
}
df = pd.DataFrame(data)

DB_SERVER = "YourServerName,1433"
DB_TABLE = "YourDatabase.dbo.YourTable"
TEMP_CSV = "temp_bcp_data.csv"
ERROR_LOG = "bcp_error.log"

try:
    logging.info("Attempting insert with SQL Server login (CSV method)...")
    bulk_insert_bcp(
        df=df,
        target_table=DB_TABLE,
        db_server_port=DB_SERVER,
        temp_file=TEMP_CSV,
        error_log_file=ERROR_LOG,
        username="your_sql_user",
        password="your_sql_password"
    )
    logging.info("Successfully inserted data!")

except Exception as e:
    logging.error(f"Data insert failed: {e}")

2. Native Insert (Fastest, Advanced)

This method is significantly faster (potentially 100x+) than the CSV method because it skips the text conversion step. It's ideal for very large DataFrames.

It works by converting the DataFrame to SQL Server's internal binary format (.dat file) and generating a corresponding XML format file (.xml).

Note: This function requires a table_schema dictionary so it knows how to convert the data.

Python

import pandas as pd
import numpy as np
import logging
from bcp_utils import bulk_insert_bcp_native

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Example data, including nulls
data = {
    'col_a_int': [1, 2, np.nan, 4],
    'col_b_varchar': ['hello', 'world', '!!', np.nan],
    'col_c_date': [pd.Timestamp('2025-01-01'), pd.NaT, pd.Timestamp('2025-01-03'), pd.Timestamp('2025-01-04')],
    'col_d_float': [1.23, 4.56, 7.89, np.nan]
}
df = pd.DataFrame(data)

# You MUST define a schema that matches your SQL table
# This is required for the native binary conversion
my_schema = {
    'col_a_int': {'type': 'INT'},
    'col_b_varchar': {'type': 'VARCHAR', 'max_length': '100'},
    'col_c_date': {'type': 'DATE'},
    'col_d_float': {'type': 'FLOAT'}
}

DB_SERVER = "YourServerName,1433"
DB_TABLE = "YourDatabase.dbo.YourTable"
TEMP_BASE = "temp_native_batch"  # Will create .dat and .xml files
ERROR_LOG = "bcp_error.log"

try:
    logging.info("Attempting insert with Trusted Connection (NATIVE method)...")
    bulk_insert_bcp_native(
        df=df,
        table_schema=my_schema,
        target_table=DB_TABLE,
        db_server_port=DB_SERVER,
        temp_file_base=TEMP_BASE,
        error_log_file=ERROR_LOG,
        use_trusted_connection=True,
        cleanup_temp_files=False  # Set to True in production
    )
    logging.info("Successfully inserted data using NATIVE format!")

except Exception as e:
    logging.error(f"Data insert failed: {e}")

License

This project is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_bcp_utils-1.0.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_bcp_utils-1.0.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file py_bcp_utils-1.0.0.tar.gz.

File metadata

  • Download URL: py_bcp_utils-1.0.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for py_bcp_utils-1.0.0.tar.gz
Algorithm Hash digest
SHA256 86b48cfcc5734f465a926f05e8898268b44b49b63efa485756cdfaeeee2dd8cf
MD5 352ed7cd78696e04adc9433a2ecf6cb4
BLAKE2b-256 378039b6b16a354cec9af323dcb627d32b40bfd5b32cf2e2a88a0b6ed09522cb

See more details on using hashes here.

File details

Details for the file py_bcp_utils-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: py_bcp_utils-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for py_bcp_utils-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0af54fc782734b41ce5d47abad939fe53b11ce30ff2082c7e25646cf6cc131ff
MD5 a79533d6b4b2a86f0575b99f8141bec2
BLAKE2b-256 0b75487cfb39ee30f4fb7de03404a083d6f9a75dfb15ac8a6c76196b27f2a0d2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page