PrestaShop Database: Key Tables Every Store Owner Should Know

383 views

Why Understanding the Database Matters

PrestaShop stores everything — products, orders, customers, settings, translations, images, prices — in a MySQL database. While you can manage most things through the admin panel, understanding the database structure gives you superpowers. You can diagnose problems faster, perform bulk operations that would take hours through the UI, recover from errors that break the admin panel, and make informed decisions about optimization and scaling.

PrestaShop's database uses a prefix system (default ps_) for all table names. This prefix can be customized during installation, so your tables might use a different prefix. In this guide, we use the default ps_ prefix.

Product Tables

ps_product

The core product table. Contains one row per product with fundamental product data -

ColumnPurpose
id_productUnique product identifier
id_category_defaultDefault category for the product
priceBase price (tax excluded)
wholesale_priceCost/purchase price
referenceProduct reference/SKU
ean13EAN-13 barcode
quantityStock quantity (legacy, see ps_stock_available)
activeWhether the product is enabled (1) or disabled (0)
date_addCreation date
date_updLast modification date

ps_product_lang

Contains language-specific product data - name, description, meta title, meta description, link_rewrite (URL slug). One row per product per language per shop.

-- Find products missing descriptions in a specific language
SELECT p.id_product, pl.name 
FROM ps_product p
JOIN ps_product_lang pl ON p.id_product = pl.id_product
WHERE pl.id_lang = 1 
AND (pl.description IS NULL OR pl.description = '');

ps_product_shop

Multistore-specific product data. Contains price, active status, and visibility settings per shop. In single-store setups, this mirrors ps_product.

ps_stock_available

The actual stock tracking table. This is where PrestaShop reads stock quantities from (not ps_product.quantity, which is legacy).

-- Check stock for a specific product
SELECT * FROM ps_stock_available 
WHERE id_product = 42 AND id_product_attribute = 0;

ps_product_attribute

Product combinations/variants. Each row represents a specific combination of attributes (e.g., Size: L, Color: Blue). Contains price impact, weight impact, reference, and EAN for each combination.

ps_specific_price

Discounts and special prices. Handles percentage discounts, fixed-amount discounts, prices per customer group, date ranges, and quantity-based pricing.

Category Tables

ps_category

Category tree structure using nested sets (nleft, nright, level_depth). Key columns include id_parent, active, position, and date_add.

ps_category_lang

Language-specific category data - name, description, meta title, meta description, link_rewrite.

ps_category_product

Many-to-many relationship between products and categories. Each row links a product to a category with a position value for ordering.

-- Find all products in a specific category
SELECT p.id_product, pl.name, cp.position
FROM ps_category_product cp
JOIN ps_product p ON cp.id_product = p.id_product
JOIN ps_product_lang pl ON p.id_product = pl.id_product AND pl.id_lang = 1
WHERE cp.id_category = 5
ORDER BY cp.position;

Order Tables

ps_orders

The most important commerce table. Each row is a completed order. Key columns -

ColumnPurpose
id_orderUnique order ID
referenceOrder reference code (e.g., ABCDEF123)
id_customerCustomer who placed the order
id_cartCart that became this order
current_stateCurrent order status ID
paymentPayment method name
total_paidTotal amount paid
total_paid_tax_inclTotal with tax
total_products_wtProducts total with tax
total_shipping_tax_inclShipping cost with tax
date_addOrder date

ps_order_detail

Individual line items within an order. Contains product_id, product_name, product_quantity, product_price, unit_price_tax_incl, and total_price_tax_incl.

-- Get order summary with line items
SELECT o.reference, o.date_add, o.total_paid_tax_incl,
  od.product_name, od.product_quantity, od.unit_price_tax_incl
FROM ps_orders o
JOIN ps_order_detail od ON o.id_order = od.id_order
WHERE o.id_order = 12345;

ps_order_state and ps_order_state_lang

Define order statuses (Awaiting payment, Payment accepted, Shipped, Delivered, etc.) and their translated names.

ps_order_history

A log of all status changes for each order, with timestamps. Useful for tracking order processing speed.

Customer Tables

ps_customer

Customer accounts. Key columns include email, passwd (hashed), firstname, lastname, id_default_group, newsletter (subscription status), active, and date_add.

-- Find customers who registered but never ordered
SELECT c.id_customer, c.email, c.firstname, c.lastname, c.date_add
FROM ps_customer c
LEFT JOIN ps_orders o ON c.id_customer = o.id_customer
WHERE o.id_order IS NULL
AND c.active = 1;

ps_address

Customer addresses. Linked to customers via id_customer. Contains company, firstname, lastname, address1, address2, postcode, city, id_country, id_state, phone, phone_mobile.

ps_guest

Tracks anonymous visitors before they register or log in. Linked to carts for guest checkout scenarios.

Cart Tables

ps_cart

Shopping carts. Contains id_customer, id_address_delivery, id_address_invoice, id_currency, id_lang, and date_add. Not every cart becomes an order — abandoned carts remain here.

ps_cart_product

Products in each cart, with quantities and selected attributes/combinations.

-- Find abandoned carts from the last 7 days with products
SELECT c.id_cart, cu.email, c.date_add, 
  GROUP_CONCAT(pl.name SEPARATOR ', ') AS products
FROM ps_cart c
JOIN ps_customer cu ON c.id_customer = cu.id_customer
JOIN ps_cart_product cp ON c.id_cart = cp.id_cart
JOIN ps_product_lang pl ON cp.id_product = pl.id_product AND pl.id_lang = 1
LEFT JOIN ps_orders o ON c.id_cart = o.id_cart
WHERE o.id_order IS NULL
AND c.date_add > DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY c.id_cart;

Configuration Tables

ps_configuration

PrestaShop's key-value store for all settings. Every option you configure in the back office is stored here. Key columns are name (setting key) and value (setting value).

-- Check your shop's current settings
SELECT name, value FROM ps_configuration 
WHERE name IN ('PS_SHOP_DOMAIN', 'PS_SHOP_DOMAIN_SSL', 
  'PS_SSL_ENABLED', 'PS_SHOP_ENABLE', 'PS_LANG_DEFAULT');

ps_configuration_lang

Language-specific configuration values. Some settings (like email templates) have different values per language.

Module and Hook Tables

ps_module

List of all installed modules with their version numbers. One row per module.

ps_hook

All available hooks in the system. Hooks are extension points where modules can inject content or behavior.

ps_hook_module

Maps which modules are attached to which hooks, with their display position. This controls the execution order when multiple modules use the same hook.

-- Find all modules attached to a specific hook
SELECT h.name AS hook_name, m.name AS module_name, hm.position
FROM ps_hook_module hm
JOIN ps_hook h ON hm.id_hook = h.id_hook
JOIN ps_module m ON hm.id_module = m.id_module
WHERE h.name = 'displayHeader'
ORDER BY hm.position;

SEO and URL Tables

ps_meta and ps_meta_lang

URL patterns and meta information for controller pages (index, category, product, cms, etc.).

ps_shop_url

Maps domains and URIs to shops. Critical for multistore setups and should never be modified carelessly.

Image Tables

ps_image

Product images with position and cover flag. Links to ps_product via id_product.

ps_image_lang

Language-specific image alt text and legend.

Common Database Operations

Bulk Price Updates

-- Increase all prices by 10%
UPDATE ps_product SET price = price * 1.10;
UPDATE ps_product_shop SET price = price * 1.10;

Bulk Enable/Disable Products

-- Disable all out-of-stock products
UPDATE ps_product p
JOIN ps_stock_available sa ON p.id_product = sa.id_product 
  AND sa.id_product_attribute = 0
SET p.active = 0
WHERE sa.quantity <= 0;

Find and Fix Orphaned Data

-- Find products that exist but have no language data
SELECT p.id_product FROM ps_product p
LEFT JOIN ps_product_lang pl ON p.id_product = pl.id_product
WHERE pl.id_product IS NULL;

Database Safety Rules

  • Always back up before modifying data
  • Never modify ps_shop_url directly — use the admin panel
  • Never change employee passwords directly — use the password reset feature
  • Never drop tables created by modules — uninstall the module instead
  • Always use transactions for multi-table updates
  • Test queries with SELECT before running UPDATE or DELETE

For more details, read our guides: Database Cleanup: Why Your PrestaShop Store Gets Slower Over Time and Performance Tuning Your PrestaShop Store: From Database Queries to Full Page Cache.

Was this answer helpful?

Still have questions?

Can't find what you're looking for? Send us your question and we'll get back to you quickly.

Loading...
Back to top